关于作者:
大家好,我是Leetcode 2020--2022,连续3年金牌获得者,和亚洲区域赛铜牌获得者,
先后在字节和大疆从事技术研发,现在是阿里达摩院的扫地僧,面试专家,CSDN博客专家。
对算法一定的见解,是一个刷题10年的算法爱好者 ,利用工作之余刷leetcode。成为leetcode官方答案贡献者之一。
7天课程目录,免费!踢馆抖音算法 (7天刷新法)
1. 第一天:一个视频教会你时间复杂度和空间复杂度 0912
2. 第二天:一个视频教会你必考的8种数据结构(视频,图文并茂) 0913
3. 第三天:一个视频教会你常用的8中解题方法和算法模版(简直不要太简单) 0912
4. 第四天:一个视频教会你 6大高频考点 常用操作技巧,常用的字符,数组,类型(独家) 0911
5. 第五天: Top10,最高频题,99%命中面试题(字节,快手,shapee,大疆, 华为,蔚来 ) ok
6. 第六天: Hot 20 , 大厂面试算法真题,95%命中(精选: 京东,美团,小米,拼多多,网易)(非算法工程师误入) 0910
7. 第七天: Top5, 经典热题5,90%命中面试题(剑指offer)
要求
1.核心代码,记住代码模版
2.最具有代表的一道题目
3.记住各种的特点,使用场景
1.双指针 2个指针 有序 (2数之和)
2.二分查找 中间值 有序
3.滑动窗口 连续
4.递归 4要素
6.分治: 分块, 和二分一样,和归并排序一样,不同的是分治是全部二分
7.回溯 返回 找到所以可能
8. DFS 深度 用到栈 二叉树
9 . BFS 广度 用到队列:LinkList 二叉树
表格:8种解题方法表格:
指针相关解法对比
双指针: 有需要排序 一般是头尾2个指针, 然后进行交叉移动i++,j--
二分查找: 有序 一般是头尾2个指针,中间值。指针移动不同:移动i=m+1或者m-1
滑动窗口: 连续
递归解法对比:重点(3者的代码对比)
1.分治: 分块, 和二分一样,和归并排序一样,不同的是分治是全部二分
2.回溯 返回
3. DFS 深度
DFS和回溯解法对比
回溯算法=DFS+剪枝(后面不走了)
回溯:递归后回上一层
DFS:一直走到底。不撞南墙不回头
DFS和BFS解法对比
共同点:一般题目都可以使用这2个一起解决
DFS :递归+栈
BFS: 2次循环+队列
双指针
双指针常用于数组、链表两种线性表(有序)数据结构相关的题,具体又分为
相向双指针:
两个指针一头一尾往中间移动
多应用于数组的连续子序列或两两组合,有规律的缩小范围
单向双指针
两个指针往同一个方向移动(没想到什么场景后续补充吧)
快慢指针:
通常慢指针向前走一步,快指针向前走两步
多用于链表、因为链表无法直接通过索引访问
通常利用快慢指针找到链表的中点或公共节点
二分法
常用于有序数组,取中点二分后按一定规则只取其中一边再继续二分,多用于查数
滑动窗口
常用于连续子序列的长度、统计量例如总和、计数等最优值问题
递归★
递归是指一个函数在运行时调用自己,框架如下
def recursion(params): #1.函数输入参数
if params==1: #2.递归终止条件
return 0
params=params-1
res=1+recursion(params) #3.调用自身
return res #4.返回值
递归有时不是直接的最优解题方法,但却是最基本、一定能解题的思想。
分治法
是一种特殊的递归,将问题进行分解,每个分解部分都有可能调用自己即递归到下一层,总结就是一个函数会同时多次或有选择性地调用自己、只是入参具体值不相同
回溯法★
一种通过探索所有可能的候选解来找出所有的解的算法。如果候选解被确认不是一个解(或者至少不是最后一个解),回溯算法会通过在上一步进行一些变化抛弃该解,即回溯并且再次尝试。(力扣定义)
是一种特殊的递归,常用于枚举组合+过滤或去重(可选)场景:
1.尝试一种路径,层层递归(调用自己)
2.找到答案并返回答案(返回值)
3.找不到答案返回上一层(终止条件)
4.尝试其他路径(调用自己)
去重前需保证枚举集有序
解决什么问题
回溯算法适用于以下的场景。
组合问题:N个数里面按一定规则找出k个数的集合
切割问题:一个字符串按一定规则有几种切割方式
子集问题:一个N个数的集合里有多少符合条件的子集
排列问题:N个数按一定规则全排列,有几种排列方式
棋盘问题:N皇后,解数独等等
深度优先搜索(Depth First Search, DFS)★
针对树结构,从根节点走一个分支到底后,返回最近的非叶子节点再走另一个分支走到底,这样直到把所有节点遍历完成
up主总结是回溯=DFS+剪枝,但我觉得回溯也不必须剪枝(上方回溯定义),所以是不是更合适的说DFS也是一种回溯
need-to-insert-img
need-to-insert-img
广度优先搜索(Breadth First Search, BFS)
针对树结构,从根节点一层一层遍历子节点,直到所有节点遍历完成。
比起DFS,BFS应用偏少,常用于层序遍历、最短路径场景。
一般来说,数据结构和算法会连在一起考,这里,我把面试核心知识点列了出来,大家可以参考学习,逐个击破。
栈与队列:先进先出、后进先出
线性链表
查找:顺序查找、二分查找
排序:交换类、插入类、选择类
树、二叉树、图:深度优先(DFS)、广度优先(BFS)
递归
分治
滑窗
三大牛逼算法:回溯、贪心、动态规划(DP)
算法模板
双指针模版
/*(1)定义两个边界指针*/
int left =0;//左边界
int right = num.size() -1;//右边界
while(left
/*(2)定义两个快慢指针*/
ListNode*s = head;//慢指针
ListNode*f = head->next;//快指针
while (s != f){/*执行操作*/}
回溯算法
backtracking() { if (终止条件) { 存放结果; } for (选择:选择列表(可以想成树中节点孩子的数量)) { 递归,处理节点; backtracking(); 回溯,撤销处理结果 }}
或者是这个:
public void helper(options, result) {
// 1. 在for循环之前做“判断”
if (list.size() ...) {
do something ...
return;
}
// for loop
for loop {
// 可能在这里还需要做一些判断:1.操作是否合法;2.操作是否重复
// 3. 在递归之前做“选择”
result.add(element);
// 2. 在for循环里面做“递归”
helper(options, result);
// 4. 在递归之后做”撤销“
result.removeLast();
}
}
回溯的代码模版
private void backTracking(int n, List list, int left, int right, String curStr) {
if (left < right) {// (不符合退出条件)右边的括号大于左边的括号的时候,就需要终止了,终止一个地方
return;
}
if (left == n && right == n) {// 达到条件,终止条件
list.add(curStr); // 保存结果,并退出
return;
}
if (left < n) {// 移动指针, 回溯,
backTracking(n, list, left +1, right, curStr +"(");
}
if (right < left) {// 移动指针, 回溯,
backTracking(n, list, left, right +1, curStr +")");
}
}
二分查找法
二分查找模版
vector&nums
int left=0;//左边界
int right=nums.size()-1;//右边界
int mid=0;
while(left<=right){
mid=(left+right)/2;
if(target==nums[mid]){/*操作*/ }
if(target
right=mid-1;
}
else{
left=mid+1;
}
}
class Solution {public: int searchInsert(vector