二分
-
【33】搜索旋转数组
- mid=target:直接返回
- mid<right:左图情况
- mid>left:右图情况
-
func search(nums []int, target int) int { l, r, mid := 0, len(nums)-1, 0 for l <= r { mid = (l + r) / 2 if nums[mid] == target { return mid }else if nums[mid]<nums[r]{ if target>nums[mid] && target<=nums[r]{ l = mid + 1 }else{ r = mid - 1 } }else{ if target>=nums[l] && target<mid{ r = mid-1 }else{ l = mid+1 } } } return -1 }
-
【153】寻找旋转排序数组中的最小值:二分,分两种情况
-
【34】在排序数组中查找元素的第一个和最后一个位置:两次二分
-
【74】搜索二维矩阵:两次二分
-
【162】寻找峰值:二分,如果mid是峰值直接返回,否则向更高的地方走
二分答案
- 【222】完全二叉树的节点个数:二分并验证是否有n个节点
双指针
两个指针或下标,在数组、链表上移动。时间复杂度O(n)。
同向移动(滑动窗口)
两指针从同一端移动到另一端
- 【3】最长无重复子串:又指针移动并记录字母,如果有重复的就不断右移左指针
- 【76】最小覆盖子串:又指针移动并记录字母,如果满足覆盖就不断更新答案并右移左指针
- 【209】长度最小的子数组:找出该数组中满足其和 ≥ target 的长度最小的 连续子数组
- 【offer 48】最长不含重复字符的子字符串:右指针记录数,当出现重复值,左指针右移删除
- 【424】替换后的最长重复字符:滑动窗口时,枚举变成各种相同字母的最长结果
- 【567】字符串的排列:hash记录第一个字符串所有字母和数目,又指针向右走,遇到有的计数减一,计数边负或者遇到没有的就把左指针右移。
- 【611】有效三角形的个数:排序,枚举第一个数,和第二个数,第三个数为一个向右走的指针,符合两边之和大于第三边就向右走
- 合并两个有序数组、链表
- 原地删除数组的重复值
反向移动
从两端向中间逼近答案
-
【11】盛最多水的容器:不断计算体积,向中间移动短的那个
-
【15】三数之和:排序,枚举第一个数,剩下两个数lr向中间找
-
【42】接雨水:先移动短板的那边,更新短板和计算是否有雨水
-
有序数组上两数之和
-
最接近的三数之和:排序+有序数组的两数之和
-
【18】四数之和:排序+双重for+双指针
-
【167】两数之和 II - 输入有序数组:有序数组两数之和
快慢指针
-
【141】环形链表:快慢指针从头开始走,快指针走两步,慢指针走一步,会在环的入口处相遇
-
为什么会相遇,在环内,快指针每次比慢指针快一步,一定会赶上
-
为什么在入口相遇:假设总长度n,环外长度x,环内长度n-x
- 当low到入口时,low坐标0,fast坐标x%(n-x)
- fast还需要n-x-x%(n-x)步赶上low
- 经过n-x-x%(n-x)步后,fast在n-x%(n-x)=0的位置上,正好是起点
-