代码随想录训练营二刷 总结 | 完结撒花

代码随想录训练营二刷 总结 | 完结撒花

总结:

从最开始找不到如何做算法题的门路,面对算法题一筹莫展,到现在二刷完结看题基本都知道怎么回事有思路了,感谢卡哥带我入门,学一样东西往往入门是颇具难度的,入门之后才是个人努力闪光的时候。
之后我打算刷一下卡哥新更新的图论,然后做一做hot100在不知道题目类型的情况下练习。

一、二分法

1、维持好循环不变量。

2、搜索结果如果是单点,结果由mid=target得出;搜索结果如果是区间范围或者是单区间(如求平方根只要整数向下取整即为单区间)这种要一个区间边界一个搜索,分开搜索,写到一块容易出错误。

二、双指针法

双指法的使用比较灵活,有单向的快慢双指针,也有双向指针法,也有两个指针指向相邻元素,此外还有灵活的使用全局变量记录要移动的位置。

三、滑动窗口

滑动窗口即为,不断移动窗口的起始位置和结束位置,直到得到我们想要的结果。

最典型的就是两层for循环,外层控制起始位置,内层控制结束位置。只不过滑动窗口是一层for循环控制结束位置,满足目标条件后,再移动起始位置,直至不再满足条件,然后再移动借宿位置。

四、链表操作

注意使用虚拟头结点。对于判断有环无环,可以用快慢指针,一个走两步一个走一步,能相交即为有环,然后一个从头结点出发一个从相交点出发,再次相交时即为环的入口。

五、哈希表

什么时候想到用哈希法,当我们遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法。当我们想使用哈希法来解决问题的时候,我们一般会选择如下三种数据结构。数组、set (集合)、map(映射)

两数之和、三数之和、四数之和,主要set、map、双指针的使用,三数之和、四数之和的去重、剪枝。

六、字符串

注意翻转、双指针、KMP。

七、栈和队列

栈: 栈在系统中的应用、括号匹配问题、字符串去重问题、逆波兰表达式问题

队列:滑动窗口最大值问题、求前 K 个高频元素

卡哥总结、注意大顶堆和小顶堆,优先级队列java中是PriorityQueue。

八、二叉树

求普通二叉树的最近公共祖先用后序遍历,求二叉搜索树的最近公共祖先直接从上向下搜索,搜索两个节点构成的区间,第一个在区间内的节点即为最近公共祖先。

递归何时需要返回值

再来看返回值,递归函数什么时候需要返回值?什么时候不需要返回值?这里总结如下三点:

  • 如果需要搜索整棵二叉树且不用处理递归返回值,递归函数就不要返回值。(这种情况就是本文下半部分介绍的113.路径总和ii)

  • 如果需要搜索整棵二叉树且需要处理递归返回值,递归函数就需要返回值。 (这种情况我们在236. 二叉树的最近公共祖先 (opens new window)中介绍)

  • 如果要搜索其中一条符合条件的路径,那么递归一定需要返回值,因为遇到符合条件的路径了就要及时返回。(本题的情况)

九、回溯

组合、分割、子集、排列、棋盘、其他

组合问题:

元素可以重复使用index无需加1,元素不可以重复使用需要从下一个位置开始index+1。

如果组合数是固定个数的可以剪枝,for循环的次数小于n了就停止。

对于数组中有重复数字,但是要求结果集不能重复,需要树层去重。

分割问题:注意操作字符串的边界问题。

子集问题:

如果收集所有节点,即叶子结点和非叶子节点。

求递增子序列,如3,7,6,7 。由于不能排序树层去重,就无法使用used数组或者i > index && nums[i]== nums[i-1],因为相同的数并不挨着。又得解决树层中相同的数不能重复使用,就可以在树层间使用set数组,每递归进入下一层就是一个新数组。

求全排列,由于排列讲究顺序,如1,2,3排列结果会有2,1,3。这样就不能指定for循环的开始位置为当前数的下一个,而是固定从0开始,但是需要使用一个数组记录下来哪些使用过滤哪些没有使用,要纵向记录,因为纵向不能重复使用数字,递归标记,回溯后就没有标记,只影响纵向收集。

对于有重复数字的全排列,纵向横向都要去重,for从0开始,避免纵向重复使用used数组记录,为true为使用过,为false为没使用过,即used[i]=true跳过,横向去重需要数组排序,当nums[i]=nums[i-1]时,used[i-1]=false是回溯完的,需要树层去重。

十、贪心

注意区间问题。

十一、动态规划

分为:背包问题、打家劫舍、股票问题、子序列问题

背包问题:一维数组,dp[j] = Math.max(dp[j], dp[j-nums[i]] + nums[i])。

01背包遍历顺序:先物品后背包,物品正序,背包逆序。

如若背包正序则会出现同一个物品重复放入,如物品1重量为1,背包空间为1时放入了,背包空间为2时又放入了。
如果先背包后物品,为了避免重复放入背包依然是逆序,背包容量固定时,每种背包容量只能放入一个物品,即为最大的物品,小的物品都放不进来或者被覆盖了。

求组合数排列数:dp[j] += dp[j - nums[i]]

完全背包遍历顺序:物品背包没有先后顺序,物品背包都是正序。因为同一个物品不限量可以放入多次,在背包采用正序中。

完全背包求组合数,物品在外,背包在内。求排列数,背包在外,物品在内。

股票问题:每天是有两种状态的,持有或者不持有。

定义时都要这么定义,也可以简化为dp[0],dp[1]。

定义dp[i][0]表示第i天持有股票手中金额的最大值,dp[i][1]表示第i天不持有股票手中金额的最大值。
注意,这里的持有可以是之前持有的,也可以是当天才持有的,不持有可以是之前就没持有过,也可以说当前才卖出变成了没持有。

下面是一个每天都可以买卖的例子。

dp[0] = Math.max(dp[0], dp[1] - prices[i]);

dp[1] = Math.max(dp[1], dp[0] + prices[i]);

最后就是子序列问题,最长递增子序列、最长连续递增子序列,最长连续子数组,最长重复子序列

十二、单调栈:

一般是求左边或者右边第一个最大的元素时使用。

有两个经典的问题:接雨水和矩阵面积。解题思路(2,1,3)和(1,2,3)

  • 9
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
第二十二天的算法训练营主要涵盖了Leetcode题目中的三道题目,分别是Leetcode 28 "Find the Index of the First Occurrence in a String",Leetcode 977 "有序数组的平方",和Leetcode 209 "长度最小的子数组"。 首先是Leetcode 28题,题目要求在给定的字符串中找到第一个出现的字符的索引。思路是使用双指针来遍历字符串,一个指向字符串的开头,另一个指向字符串的结尾。通过比较两个指针所指向的字符是否相等来判断是否找到了第一个出现的字符。具体实现的代码如下: ```python def findIndex(self, s: str) -> int: left = 0 right = len(s) - 1 while left <= right: if s[left == s[right]: return left left += 1 right -= 1 return -1 ``` 接下来是Leetcode 977题,题目要求对给定的有序数组中的元素进行平方,并按照非递减的顺序返回结果。这里由于数组已经是有序的,所以可以使用双指针的方法来解决问题。一个指针指向数组的开头,另一个指针指向数组的末尾。通过比较两个指针所指向的元素的绝对值的大小来确定哪个元素的平方应该放在结果数组的末尾。具体实现的代码如下: ```python def sortedSquares(self, nums: List[int]) -> List[int]: left = 0 right = len(nums) - 1 ans = [] while left <= right: if abs(nums[left]) >= abs(nums[right]): ans.append(nums[left ** 2) left += 1 else: ans.append(nums[right ** 2) right -= 1 return ans[::-1] ``` 最后是Leetcode 209题,题目要求在给定的数组中找到长度最小的子数组,使得子数组的和大于等于给定的目标值。这里可以使用滑动窗口的方法来解决问题。使用两个指针来表示滑动窗口的左边界和右边界,通过移动指针来调整滑动窗口的大小,使得滑动窗口中的元素的和满足题目要求。具体实现的代码如下: ```python def minSubArrayLen(self, target: int, nums: List[int]) -> int: left = 0 right = 0 ans = float('inf') total = 0 while right < len(nums): total += nums[right] while total >= target: ans = min(ans, right - left + 1) total -= nums[left] left += 1 right += 1 return ans if ans != float('inf') else 0 ``` 以上就是第二十二天的算法训练营的内容。通过这些题目的练习,可以提升对双指针和滑动窗口等算法的理解和应用能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

当年拼却醉颜红

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值