Skip to content

wangyeming/AlgorithmNote

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

85 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

算法学习笔记

书单

其它目录

感悟

大家知道我并非科班出身,算法方面一直是我的薄弱之向,两面微软电面,很简单的题目被裸面的我写的一塌糊涂。 面试中手写算法题考察的其实是三个方面,『数据结构』,『编程语言』,『算法』。优秀的程序员应该具备这三方面的能力。 我希望跟随者书本题目的练习和总结,利用github新建这个项目,为自己的算法学习立一个规划。

代码

我会优先用java实现我的算法,有时间的情况下,我会用python3再实现一遍。

书中的题目我尽量都完成,题目我会简单的标注在代码的注释里,代码也会写一些思路和核心要点。

算法的掌握程度

  • 了解通常情况下的最优解的原理,能讲清楚问题的分析步骤和处理方式。

  • IDE下能参考别人的实现写出答案

  • IDE下能在规定时间内自己写出答案

  • 白板或纸能在规定时间内自己写出答案

数据结构

常见的数据结构包括但不限于:

字符串

数组

链表

队列和栈

哈希表

编程语言

我的主力编程语言是Java,相比于C++和Python而言呢,优点和缺点也很明显:

优点:有8种基本的数据类型,byte(字节型)、short(短整型)、int(整型)、long(长整型)、float(单精度浮点型)、double(双精度浮点型)、boolean(布尔型)、char(字符型) 以及固定内存开销的数组。可以基本做到对内存开辟的可控。相比于python,虽然少了很多奇淫巧技的写法,但是也断绝了很多人利用python系统函数实现算法却对时间和内存开销一无所知的情况。

缺点:相比于C++,Java无法操作指针,导致一些可以利用指针简化的操作和传值会比较繁琐。相比于python,缺少灵活性,例如函数的返回值不够灵活,更多的模版代码。

算法

  • 首先是最基础的排序算法,

十大经典排序算法(动图演示)

排序算法总结

排序算法中,快排和堆排的思想很重要,他们分别有可以衍生出新的题目:

快排的思想:剑指offer-40 最小的K个数(TopK问题)

归并排序的思想:剑指offer-51 数组中的逆序对

堆排的思想: LeetCode-23 合并K个排序链表

  • 其次是查找算法,比如说最基础的二分查找:

剑指offer-3-2 不修改数组找出重复的数字

剑指offer-11 旋转数组中的最小数字

剑指offer-53-1 在排序数组中查找数字

剑指offer-53-2 0~n-1中缺失的数字

编程之法-4-1 有序数组的查找

  • 递归思想,很基础也很直观,通常不一定最优,但是一般实现最简单。

例如二叉树遍历,所有遍历方式都可以用递归来写,是最简单的。

再比如剑指offer-10 斐波那契数列/青蛙跳台阶问题/覆盖问题 等等。

  • 原地操作

这里通常指的是字符串/数组的原地操作,比如说,原地旋转一个字符串,考察点是内存开辟的高度敏感。

编程之法-翻转一句话中的单词

  • 分治思想

所谓的分治思想,就是分而治之,将一个难以直接解决的大问题,分割成一些规模较小的相同问题,以便各个击破,分而治之。快排就是分治思想的重要例子。

  • 双指针法

双指针常见于各类算法题,有很多演变版本,比如说快速排序中,partition这一步,就有前后指针,左右指针两种不同的双指针法。

所谓前后指针,通常也称作为快慢指针,最常见的例子就是:剑指offer-23 链表中环的入口节点, 通过快慢指针,巧妙的判断链表是否有环。

所谓左右指针,通常也称为为对撞指针,最常见的例子就是:剑指offer-21 调整数组顺序使奇数位于偶数前面,指正从数组或者双向链表的头部和尾部向中间靠拢的思想

而前后指针和左右指针,还可以搭配起来使用,例如编程之法-2-7 荷兰国旗 三路指针,其中指针1,2可以看作前后指针,指针2,3可以看作左右指针

  • 位运算

一般设计位运算的题目都比较巧妙,首先我们需要了解计算机二进制的一些基础知识

原码, 反码, 补码 详解

同时,像基本的位运算,比如位与,位或,位异或,按位取反,位左移,右移等操作,要做到了解原理,对熟悉的编程语言的位运算符号也要熟悉。

例如剑指offer-56-1 数组中数字出现的次数这道题,利用了异或运算。

  • 动态规划

动态规划的题目,我个人掌握的还不够好,个人以为,动态规划(DP)的核心思想也就是建立起状态转移方程,例如剑指offer-10 斐波那契数列/青蛙跳台阶问题/覆盖问题

这道题,斐波那契数列定义本身就是一个状态转移方程,通过DP我们可以记住中间计算结果,避免了递归的大量重复运算。

  • 贪心法

贪心法(英语:greedy algorithm),又称贪婪算法,是一种在每一步选择中都采取在当前状态下最好或最优(即最有利)的选择,从而希望导致结果是最好或最优的算法。

例如 剑指offer-14 剪绳子, 如果用动态规划算法的话,时间复杂度O(n^2),空间复杂度O(n),而贪婪算法的时间复杂度则非常低。

不过贪心法并不一定对所有题目都适用,而且由于需要数学证明,所以难度相对来说比较高。

  • 回溯法

所谓的回溯法其实就是暴力搜索的一种方式,我们知道,很多算法题至少有一个暴力破解的解法,时间复杂度可能很复杂但是至少是有效的。而回溯法是一种选优搜索法,又称为试探法,

按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步。例如

剑指offer-2112 矩阵中的路径

很多类似这种二维矩阵的查找阿,匹配啊,都是回溯法的思路。

以上是我个人微不足道的总结,以后会随着自己刷题的深入,不断更新和修正内容。

About

田野光的算法学习笔记

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published