ARTS-WEEK-002

需要抓紧时间的一周。

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 的概念、原因和解决。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 对象的引用,可以改变。

Missing Semester - Git

Share:

程序员修炼之道 - 通向务实的最高境界

提示3 你有权选择

你的工作环境很糟糕?你的工作很无聊?尝试纠正它。不过,不要一直试下去。正如 Martin Fowler 说的,“你可以去改变组织,或是让自己换一个组织。”

如果你的技术过时了,安排时间(你自己的时间)学习一些看起来有趣的新东西。这是一种自我投资,只有为此而加班才是合理的。

想远程工作?要求过了吗?如果他们说不行,就去找个说行的人。

这个行业给了你一系列非凡的机遇。积极主动点,掌控这些机遇。

提示4 提供选择,别找借口

在你的职业发展、学习教育,以及你的项目、每天的工作等各方面对你自己负责,对你的行为负责,这是务实哲学的基石之一。

责任意味着你对某事积极认同。你保证事情能搞定,并为之作出承诺,但你不必直接掌控事情的每个方面。

当你决定对一个结果承担责任时,要明白这意味着你将承担相关的义务。

给出选择,而不是找借口。不要说搞不定;解释一下要做些什么才能挽回这个局面。

posted @ 2020-06-06 12:07  Jeff_p  阅读(210)  评论(0编辑  收藏  举报