• 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 提供选择,别找借口

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

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

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

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

  • 相关阅读:
    vue学习笔记 样式 class style(五)
    vue学习笔记 计算属性(四)
    vue学习笔记 模板语法(三)
    vue学习笔记 实例(二)
    vue学习笔记 概述(一)
    Babel指南——基本环境搭建
    手动es6编译es5(命令行)
    TrimPath
    git 远程仓库管理
    CSS左侧固定宽 右侧自适应(兼容所有浏览器)
  • 原文地址:https://www.cnblogs.com/pyx0/p/13054189.html
Copyright © 2020-2023  润新知