实战题目
Array 题目
容器装水
移动零
爬楼梯
3sum (高频老题) 这题需要反复练习,问题很多
Linked List 实战题目
翻转链表
两两交换链表节点
链表中的环判断
链表中的环判断02
每k个一组翻转 : 这个要多做两遍,搞清楚需要的状态,
课后作业
排序数组中移除重复元素
数组旋转
有序list merge
有序array merge
2sum
移动零
加一操作
技巧,在for循环或者while循环中,有些情况下先执行业务逻辑再判断,可能更加合理
空间换时间,升维来降低复杂度
思考
1.仔细check那些非常规的迭代
当写出了不是正常的循环模式的时候一定要仔细检验自己的边界条件是否是正确的,比如这里
使用的是+1的模式,和平时的减一有很大的区别,导致没法向后面多走一步,走到想要的位置,这个时候很容易犯错误
if height[left] < height[right]:
while left < right and height[left+1] <= height[left]:
left=left+1
left=left+1 # 最开始没有写
else:
while left<right and height[right-1]<=height[right]:
right= right-1
right=right-1
2.逻辑的合并导致了边界条件的失效
这里在写代码的时候发现可以进行逻辑合并,但是最最开始思考的时候并没有做逻辑合并,导致代码的边界检查出错
while right < length and left <= right:
最开始写成了下面没有等号的,因为最开始的思考是left指向最左边的0,right指向left之后的第一个非零,所以left不会等于right,但是代码不容易写,逻辑合并之后变得简洁了,但是却没有修改边界条件
while right < length and left < right:
3. 尽量不要修改入参
在修改入参之后有时候产生了复用,发生非常大的副作用,这里
最开始是直接操作的k,但是下面也用到了k,于是就产生了非常大的副作用。。。
while c > 0 :
4.复杂问题拆解
有时候有些问题是单存的复杂,并不是没有思路的那种,这种问题贸然下笔可能就容易出错,需要按照下面的思路来进行拆解
复杂问题拆解为子问题
- 子问题解决需要哪些变量,解决什么问题
- 子串的开头(变量)
- 内部的反转 (问题)
- 合并子问题的时候需要哪些变量
- 两个子串之间的连接 (问题)
- 上一个子串的结尾+当前子串的开始+当前子串的结尾+下一个子串的开始
5.合并逻辑有可能可以优化边界的检查
合并逻辑有可能可以优化边界的检查,就像移动0一样,如果按照常规的思路,肯定是想着left要是左边的第一个0,right要到left后的第一个非零,这样就会多出一些边界check的代码,但是逻辑合并之后可能反而这些都不需要做了。挺有意思的。官方给的答案也是直接就是一个逻辑合并的答案,感觉还是需要多学习才行。
https://leetcode-cn.com/submissions/detail/308472794/
class Solution:
def moveZeroes(self, nums: List[int]) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
# 可以使用双指针,左边的指针指向0,右边的指向非零,一旦遇到非零就left复制,然后前进
# 感觉这个边界还是有点不容易,为了避免初始边界处理的问题,所以合并了逻辑
left = 0
for right in range(len(nums)) :
if nums[right] != 0 :
nums[left] = nums[right]
left += 1
for i in range(left,len(nums)) :
nums[i] = 0