Skip to content

Latest commit

 

History

History
106 lines (75 loc) · 7.05 KB

2018-11-19.md

File metadata and controls

106 lines (75 loc) · 7.05 KB

一. Algorithm

本次做的还是关于二分查找的问题 35. Search Insert Position。 给定一个有序数组和目标值,如果目标值在数据中,则返回对应的索引,如果不在则返回合适的插入位置索引。依旧是考察二分查找,查找元素所在索引或者大于目标值的最小索引值。 需要注意的是边界的处理,如果数组的最大值一开始就比目标值小,则插入位置是数组长度 + 1, 如果数组最小值比目标值大,则插入位置为 0。代码如下:

class Solution {
    public int searchInsert(int[] nums, int target) {
        int low = 0;
        int high = nums.length - 1;
        int mid = 0;

        if (nums.length == 0 || nums[0] > target) {
            return 0;
        }

        if (nums[nums.length - 1] < target) {
            return nums.length;
        }

        while (low <= high) {
            mid = low + ((high - low) >> 1);
            if (nums[mid] == target) {
                return mid;
            }else if (nums[mid] > target) {
                if (mid == 0) {
                    return 0;
                }
                high = mid - 1;
            }else {
                if (mid == nums.length-1) {
                    return nums.length;
                }
                if (nums[mid+1] > target) {
                    return mid + 1;
                }
                low = mid + 1;
            }
        }
        return 0;
    }
}

二. Review

本次 Review 读了 Medium 上的一篇文章: Goodbye, Object Oriented Programming

作者提到了在遵守面向对象编程三大原则:继承、封装、多态时遇到的问题,并提出了相应的解决办法让我们避免该问题,概要如下:

1. GoodBye Inheritance

作为面向对象三原则之一的继承,其最大的优点在于可以抽象特性,复用相关的属性和方法。但这也带来了如下几个问题:

  • Banana Monkey Jungle Problem: 继承可能会造成比较复杂的继承体系,导致我们需要一个类时,发现还需要引入该类的父类,而父类又有父类,类中包含的其他类对象可能又有一大堆父类。造成了所谓的: 我们 只是想要一根香蕉,结果给了我们一片香蕉林。
  • 钻石问题: 即一个子类继承了两个父类,而这两个父类又继承了同一个父类并复写了相同的方法,这会导致子类在方法调用时可能无法调用到合适的方法
  • 脆弱的基类: 当父类的方法改变时,可能会影响子类,如果子类很多,那么影响面就非常大了,严重影响已有代码
  • 无法确认的继承关系: 程序是对现实世界的抽象,而现实世界中的事物并不都有严密的继承体系,作者举了一个例子,对于一份公司的文件,如果我要存储它,既可以存储在 docuemnt -> company 路径下,又可以存储在 company -> document 路径下,这时无法给出明确的继承体系,但如果采用组合的方式,将这些层级视为文件的 tag 标签,就可以解决这个问题。

以上三个问题,对于钻石问题,最简洁的方式就是禁止多继承,比如 Java 就不允许多继承,但像是 Python 就允许多继承,其有一套多继承时的方法调用规则,问题就是如果两个父类有相同的方法,其中一个父类的方法可能永远不会被调用到。对于其他问题,作者给出的解决建议就是我们常说的 「组合优于继承」。通过依赖注入的方式,将继承变为多个对象之间的组合,这样避免了父类改变对子类的影响,同时类之间功能独立,可以灵活组合,提到了代码的扩展性。所以作者最后提到 「GoodBye Inheritance」。

2. GoodBye Encapsulation

对于封装,作者提到其最大的问题在于方法间引用的传递导致的问题。虽然我们可以将某个对象设置为私有变量,当时当从外部注入时,其传递过来的只是地址值,这就导致了如果其他的方法也传入了相同的引用,就会影响到当前使用该引用对象的方法,解决方法就是将对象进行深拷贝,避免受其他方法有相同引用可能造成的影响,但是在某些涉及到系统资源的地方并不能深拷贝,在极端情况下可能会造成问题。

3 GoodBye Polymorphism

多态虽然是面向对象编程的三大特性之一,但是通过接口,我们可以非常灵活的组合某个对象拥有的行为,在 Java 中被称为 interface, Python 中的 mixin 类,其根据行为自由组合,完全可以实现更加的合适的对象。

以上就是作者的提到的内容概要。个人实际体验中上述提到的问题确实存在,而且大多数程序员最先接触的可能都是面向对象的编程语言,因此一开始也深受面向对象编程的影响。但随着经验的增加,其实编程方式也不止面向对象编程一种,通过了解更多的编程范式我们会找到更适合的编程方式来完成我们要做的事情,耗子叔的专栏中也有编程范式游记系列,非常值得反复思考咀嚼。

三. Tip

分享个 zsh 的小工具,zsh-autosuggestions。安装后,在命令行输入命令式,可以自动提示历史命令并补全后面的命令,就像 IDE 代码提示一样,非常方便。

下面是 MacOS 的安装,

[1] brew 安装
brew install zsh-autosuggestions
【2】启用工具
source /usr/local/share/zsh-autosuggestions/zsh-autosuggestions.zsh
【3】 检测效果

安装完成后开启一个新的终端会话,输入任意命令就可以看到自动提示了:

自动提示

可以看到输入命令一部分后就会提示输入过的命令,此时只需要按方向键 【 > 】 就可以自动填充命令,无需再全部手动输入了。

四. Share

最近观察自己的时间使用情况,一些小的思考分享下。

不是这个时代碎片化了,而是出现了很多让时间碎片化的东西,然后人们沉溺于这些东西导致自己的时间碎片化了。

一上午的时间,刷两次朋友圈可能就是分钟级的中断,刷会微博或者看个抖音、其他的视频可能就是十分钟级别的中断,哪怕是知识星球甚至是极客时间,都可能是十分钟级别的中断,在加上被动的打扰和必要的去洗手间、喝水等活动,被打断的次数必然会超过自己可控的数量,叠加起来的时间就是小时级别的,更严重的是导致长时间专注的工作时间极少有能达到 1 小时的,更别提 90 分钟左右的高强度学习了。对于编程、设计以及严肃的技术性写作这样需要长时间的专注与投入的工作,对效率的影响简直就是灾难。

碎片化是可以拿来学习的,但不要为了碎片化时间的学习而将自己的时间碎片化。