@Author : Lewis Tian ([email protected])
@Link : github.com/taseikyo
@Range : 2020-11-08 - 2020-11-14
总字数:2225 个(汉字:1175,英文单词:428,数字:34,中文标点:149,英文标点:439),阅读时长约:4 分 27 秒。
*Photo by Vasilios Muselimis on Unsplash
- algorithm
- 句子逆序
- 根据快速排序的思路,找出数组中第 K 大的数
- review
- Why I Love Golang(英文)
- tip
- std::pair 作为 std::unordered_map 的 key(中文)
- GitHub Actions 入门教程(中文)
- 如何只对某些提交执行 GitHub Actions(英文)
- share
- 忘记业余项目,专注于工作(英文)
algorithm ⬆
将一个英文语句以单词为单位逆序排放。题目很简单,在 TheAlgorithms/Python 中有对应的实现,具体见 strings/reverse_words.py 和 strings/reverse_letters.py,这俩有细微区别。
def reverse_words():
return " ".join(input().split()[::-1])
print(reverse_words())
来自牛客,想吐槽给的函数参数,既然第一个参数是 vector 还要传数组大小干嘛?
class Finder {
public:
int findKth(vector<int> a, int n, int K) {
return findKth(a, 0, n - 1, n - K + 1);
}
int findKth(vector<int>&a, int l, int r, int K) {
if (l == r) return a[l];
int i = l - 1, j = r + 1;
int x = a[l + r >> 1];
while (i < j) {
do i++; while (a[i] < x);
do j--; while (x < a[j]);
if (i < j) swap(a[i], a[j]);
}
int s = j - l + 1;
if (K <= s) return findKth(a, l, j, K);
else return findKth(a, j + 1, r, K - s);
}
};
review ⬆
作者介绍了他喜欢 go 的原因,读完你发现原因其实就是 go 的特性,比如 GOPATH 的设计;模块化;包的资源管理(go get github.com/xxx/yyy);强制语言格式特性(大括号禁止换行);编译安装的路径(GOPATH/pkg 和 GOPATH/bin);跨平台编译;并发等等。
最近在开始学习 go,上面的几个特性也慢慢都接触到了,GOPATH 的设计我觉得挺妙的,导入包的时候不用去思考到底它在哪;一些格式特性也很爽,比如不用写分号(习惯 Python 之后再写 C/C++ 老是忘),大括号强制在行尾这正是我想要的,看到大括号换行的代码我强迫症真的忍不了!
另外感觉它跟 C 还挺像的,所以基础语法学起来挺快的。但是学语言都会陷入一种困境,你发现看完它的语法之后,似乎感觉已经学会了,但是好像什么都做不了。所以还是需要学以致用,像之前学 Python,写了很多爬虫之后对它的语法特性有了更深刻的了解,同时也写起来更熟练。目前学 go 可能没有很多时间去搞一些小项目,然而仅仅只是看不做的话很快就会忘记了,但这也是没办法的事。
tip ⬆
unordered_map 是 C++11 中新加入的容器,底层是用 hash 实现的,对于键值就需要有 hash 函数计算出对应的 hash 值了。
对于 int 和 string 这种基础类型,C++ 提供了计算他们的 hash 值的函数。但是对于 std::pair
或者 std::vector
这种就没有,编译器会报错:"The C++ Standard doesn't provide a hash for this type."。
下面是 unordered_map 的定义:
template < class Key, // unordered_map::key_type
class T, // unordered_map::mapped_type
class Hash = hash<Key>, // unordered_map::hasher
class Pred = equal_to<Key>, // unordered_map::key_equal
class Alloc = allocator< pair<const Key, T> > // unordered_map::allocator_type
>
class unordered_map;
第一个模板参数是键,第二个模板参数是值,第三个模板参数是 hash 函数,第四个模板参数是相等的比较函数,最后一个是分配器。
我们跳到 hash 这个结构的定义部分,如下代码,对于基础类型,都给出了对应的模板特化,也可以看到上面编译错误的报错位置。
// TEMPLATE STRUCT hash
template<class _Kty>
struct hash: public _Bitwise_hash<_Kty> {
static constexpr bool _Value = __is_enum(_Kty);
static_assert(_Value,
"The C++ Standard doesn't provide a hash for this type.");
};
template<>
struct hash<bool>: public _Bitwise_hash<bool> {
// hash functor for bool
};
template<>
struct hash<char>: public _Bitwise_hash<char> {
// hash functor for char
};
所以如果对于自定义类型,或者 hash 类没有提供模板特化的数据类型,那就需要自己定义了,最简单的方法就是:
struct pair_hash {
template<class T1, class T2>
std::size_t operator() (const std::pair<T1, T2>& p) const {
auto h1 = std::hash<T1> {}(p.first);
auto h2 = std::hash<T2> {}(p.second);
return h1 ^ h2;
}
};
int main() {
//unordered_map<pair<int, int>, int> error_mmp; // error
unordered_map<pair<int, int>, int, pair_hash> ok_mmp; // ok
}
阮一峰老师教你如何使用 GitHub Actions。我看 TheAlgorithms/Python 那个项目就使用了 GitHub Actions,之前一直想学老是忘记了。
jobs:
format:
runs-on: ubuntu-latest
if: "contains(github.event.head_commit.message, '[build]')"
如果有上述配置,任何包含 "[build]" commit 信息的提交都将触发这些作业,其他所有内容将被跳过。
jobs:
format:
runs-on: ubuntu-latest
if: "! contains(github.event.head_commit.message, 'wip')"
如果有上述配置,任何包含 "wip" commit 信息的提交都跳过这些作业。
share ⬆
我比较认同作者的观点,增加一些无用的项目对于提升自身并没有多大用处,就拿我来说,即便我现在学习了 Vue,并且仿做了几个热门应用(GitHub 上有很多这种),由于平时并不会使用到 Vue,很快我就会忘记这项技术,还不如做好自身的工作;
但是在日常工作会用到的项目或者技术却不一样,记得在本科时粗浅了解过很多语言,Java(大创要用)、ActionScript(看 B 站一个游戏视频入坑想自己做一个)、HTML+CSS+JavaScript(当时写博客的冲动)、Bash Shell(使用 Linux)、Python(写爬虫玩)和 C++(自己的工作)等等,现在回头来看,前面提到的一些语言的学习都可以说是浪费时间,当时花了很多时间和精力去学习它们,现在还是都忘了,如果当初花多点时间去干点别的,比如 BY 的选择上,或许现在会很不一样。
不过有一说一,Python 我觉得是当初学习语言最对的一个,现在基本每天都会使用,无论是对于日常一些琐碎事情的自动化,还是对于自己的手头工作的黏合,都有很大帮助。
谢谢你当初选择和学习了 Python,谢谢你一路都坚持了下来。