[经验分享] 覃超算法训练营学习笔记

本文为覃超算法训练营的课程笔记

推荐学习网站

  • 学习数据结构的动画演示网站
  • B站 覃超大魔王
  • Snailclimb/JavaGuide

工欲善其事,必先利其器

  • simple collaborative text
  • IntelliJ 10 tips (YouTube)
  • 小工具要用的很熟
  • 编码指法

以上都是顶尖职业选手区别于普通人的细节体现。

关于编程感觉-道

  1. 找到一种感觉,爱上看别人的代码。
  2. 重剑无锋,大巧不工,看到好的代码马上就想抄下来,同时自己练会学会,并且让自己写出的代码也保持这个样子。
  3. 养成阅读优秀代码的习惯,养成模拟和不断反复写的习惯,不断提高自己的代码。

关于算法学习:

  1. 数据结构不可能一遍就理解,需要反复看10遍20遍才能理解。如果你追求一遍理解,1是懒,2是没有抗挫力。
  2. 一开始可以不求甚解,但是要反复过遍数(五毒神掌)
  3. 拒绝人肉递归
    ​ 不要一层一层的去数,那样会感觉很复杂。
    ​ 为什么很复杂的递归问题,可以通过计算机很简单的几行代码解决?而人看起来就很复杂?
    ​ 因为人类的思维总是去一个一个数,而不是去寻找相似性(即重复性)。
  4. 示例:二叉树递归的复杂度分析
    ​ 时间复杂度:每个结点只访问一次,因此时间复杂度为 O(N),其中 N 是结点数量。
    ​ 空间复杂度:在最糟糕的情况下,树是完全不平衡的,例如每个结点只剩下左子结点,递归将会被调用 N 次(树的高度),因此保持调用栈的存储将是 O(N)。但在最好的情况下(树是完全平衡的),树的高度将是 log(N)。因此,在这种情况下的空间复杂度将是 O(log(N))。

关于栈对于树的递归和迭代的作用
​ 树的递归,可以在的帮助下将递归转换为迭代。

  • 深度优先搜索 -> 栈
  • 广度优先搜索 -> 队列

以下观点要牢记:

  • 链表就是树,树就是图
  • 分支就是动态规划,就是回溯,就是递归

编程之道-关于程序的本质

  1. 化繁为简:先归纳(高中的数学归纳法),后演绎。所有的方法都只有一个方法。整个宇宙就是一个题

  2. 写程序只会用到三种语言。
    a). if-else, switch -> branch
    b). for loop -> iteration
    c). recursion -> divide & conquer
    以上3条,相当于几何世界中5大公理,从它们基础上推演出以下各种各样的算法:递归,搜索,动态规划,二分搜索,贪心,数学。(注意:在大脑中回忆每种算法的思路和解题代码模板)

  3. 面试中所谓的难题:都是来找重复性,且最后是来调用递归的。

  4. 分治可以有重复问题,也可以没有重复问题。如果有重复问题,最好缓存一下,那时候就变成动态规划了。分治和动态规划是有区别的,可以认为:
    分治是一种暴力的动态规划
    动态规划是一种去重的分治,即每次在局部即取得最优解,淘汰次优解的的分治

  5. 递归问题的两种解法
    a). 记忆化搜索(LRU cache作为缓存)
    from functools import lru_cache
    @lru_cache(None)
    对于别的语言,可以开一个map或者数组。如果不用lru-cache,也就是不用递归,那就要写循环递推了,即动态规划。
    b). 动态规划
    ​ 递归->动态规划,即为 从上到下的人脑思维模式 -> 计算机从下到上的递推模式。

学过计算机和没有学过计算机的区别:

一个好问题:某些问题人类的脑子都想不明白,还要人写出程序,这怎么可能

我想给大家讲一点,这个在程序里是非常正常的,而且要训练一种思路。大家以后把算法掌握了,80%以上的面试题,以及解决业务上高难度的问题,都是那种用思维很难思考,但是你掌握好它里面的套路,或者它的重复性,用程序非常好的解决。希望大家一定要掌握这种思维。
为什么?因为程序很傻,它不会有很多的逻辑和智能的内容,它只可能去做if else,for loop和recursion。后两者就是不断的重复做一件事情。
所有你认为难的题目,它本质上都具有重复性。最关键是找重复性。而业务代码,很多if else处理业务逻辑,大部分用蛮力解决。

其他:

张一鸣 阅读《普通生物学》,找到世界的本质。他做两个产品

  1. 公司出的对外的各种产品,受众为外面的大众。
  2. 公司本身,给所有2C,今日头条,抖音等

所有的东西化繁为简,变为普适的。

训练思维模式:找到问题的本质(待整理)

爬楼梯问题变形
# 条件一:步长有三种,1,2 ,3
# 条件二:相邻步伐数不能相同

322 零钱兑换
爬楼梯:上11级台阶,每一可以走1,2步,有多少种走法?
注意:有多少走法,最少需要走多少步和走了多少步是不同的问题。

  • 有多少走法:f(n) = f(n-1) + f(n-2)
  • 最少需要走多少步:f(n) = min(f(n-1), f(n-2)) + 1
  • 走了多少步:f(n) = sum(f(n-1), f(n-2)) + 2

相当于爬楼梯问题变种:
​ 上11级台阶,每一可以走1,2,5步,问最少可以走多少步?

对于1,2两种步数,走到台阶n的最小步数:
​ f(n) = min(f(n-1), f(n-2)) + 1

coins问题(最少需要的银币数):
​ f(n) = min(n - coins[i]) for i in coins + 1

int ans = INT_MAX; // 为什么要这么写?

最少steps:
​ f(n) =sum(f(n - steps[i])) <- for i in steps

其他:

  • 灵魂提问:
    因为x =1, y = 2, 所以z = x + y = 3。这个,没有问题吧?
  • 看到一个问题。哇,太烧脑,想不明白,找重复性。好不好
  • Serendipity
    谷歌翻译:the occurrence and development of events by chance in a happy or beneficial way.
    它没有中文的翻译,或者翻译的不好。
    覃超的解释:“你经常去做一些事情,一直一直去做一些事情。这些事情你并不知道后果是好,还是不好。但是你一直坚持着,在一种偶然的情况下,最后梦想成真了。或者一个机缘巧合的原因,你得到了一个非常好的事情,但这个事情是由于你之前一直在坚持做一些事情找来的

你可能感兴趣的:([经验分享] 覃超算法训练营学习笔记)