需要抓紧时间的一周。
Algorithm:
215:Kth Largest Element in an Array (Medium)
这道题求第 k 大元素,类似于 top k,可以使用堆 heap,这里需要注意虽然逻辑上需要一个大小为 k 的小顶堆,但是实际上有个技巧是让它可以放下 k + 1 个元素,当 size == k + 1 时再去掉一个,可以精简代码。
public int findKthLargest(int[] nums, int k) {
PriorityQueue<Integer> pq = new PriorityQueue<>();
for (int val : nums) {
pq.add(val);
if (pq.size() > k) {
pq.poll();
}
}
return pq.peek();
}
利用堆解决该问题时间复杂度是 O(NlogK),空间复杂度 O(K),考虑到我们并不需要求出所有 top k,只是求第 top k 中的第 k 个,性能更好的办法是利用快速排序中的 partition 函数,不断对数组整体或部分进行 partition,比较结果 x 和 n - k(第k大等同于第 n - k 小),再确定是在 x 左边或右边递归进行 partition 再比较过程,直到 x = n - k,这时 x 就是第 k 大元素的索引。时间复杂度方面 n + n/2 + n/4 + ... + 1 是一个等比数列,求和等于 2n - 1,所以是 O(N),由于是原地分区,空间是 O(1)。最后为了减少最坏情况的发生(partition不均匀时导致白费力),需要对分区位置随机化,这里引入了 random 函数。
public int findKthLargest(int[] nums, int k) {
k = nums.length - k;
int i = 0, j = nums.length - 1;
while (true) {
if (i == j)
return nums[i];
Random random = new Random();
int pivot = i + random.nextInt(j - i);
int x = partition(nums, i, j, pivot);
if (x == k)
return nums[x];
if (x < k)
i = x + 1;
if (x > k)
j = x - 1;
}
}
int partition(int[] a, int p, int q, int pivot) {
swap(a, pivot, q);
int i = p, j = p;
for (; j < q; j++) {
if (a[j] < a[q]) {
swap(a, i, j);
i++;
}
}
swap(a, i, q);
return i;
}
void swap(int[] a, int i, int j) {
if (i == j)
return;
int tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
Review:
一篇简单和经典的文章,说明了 False Sharing 的概念、原因和解决。False sharing is a term which applies when threads unwittingly impact the performance of each other while modifying independent variables sharing the same cache line. 文章中的图片很经典,同时通过简单代码展示了问题的发生以及通过 padding 解决该问题。此外 False Sharing 中文普遍翻译为“伪共享”,而我觉得应该是错误的共享,更容易理解。
Tip:
Git 内部是一个文件系统,或者说在此之上形成的内容寻址系统(content-addressing),里面有基本的blob、tree对象,以及为了版本管理而加入的 commit 对象。blob是具体一个文件的内容变更记录对象,tree是含有一组blob指针(sha1)或tree指针的对象。每次用户提交是一个含有变更tree顶层对象指针、父母提交指针、提交元信息的对象。其中重点是变更tree顶层的对象指针,比如一次改动一个文件,提交的对象有文件变更blob,指向它的目录的变更后的tree,再上一级tree变更,直到顶级tree的变更。因此只需要顶级的tree就可以找出某一次提交所有的改动。所有 commit 对象通过父节点(可能多个)关联,形成 DAG 结构。此外还有 reference 类型,如分支、tag 等,是指向 commit 对象的引用,可以改变。
Share:
程序员修炼之道 - 通向务实的最高境界
提示3 你有权选择
你的工作环境很糟糕?你的工作很无聊?尝试纠正它。不过,不要一直试下去。正如 Martin Fowler 说的,“你可以去改变组织,或是让自己换一个组织。”
如果你的技术过时了,安排时间(你自己的时间)学习一些看起来有趣的新东西。这是一种自我投资,只有为此而加班才是合理的。
想远程工作?要求过了吗?如果他们说不行,就去找个说行的人。
这个行业给了你一系列非凡的机遇。积极主动点,掌控这些机遇。
提示4 提供选择,别找借口
在你的职业发展、学习教育,以及你的项目、每天的工作等各方面对你自己负责,对你的行为负责,这是务实哲学的基石之一。
责任意味着你对某事积极认同。你保证事情能搞定,并为之作出承诺,但你不必直接掌控事情的每个方面。
当你决定对一个结果承担责任时,要明白这意味着你将承担相关的义务。
给出选择,而不是找借口。不要说搞不定;解释一下要做些什么才能挽回这个局面。