先把链接附上,方便查找相关题目。
二分查找
初步了解:5分钟学会:二分查找_哔哩哔哩_bilibili
没有提前学习过相关概念的朋友可以点击上方的链接观看视频,讲的较为基础,可以对二分法的理念有一个初步了解
全面掌握:手把手带你撕出正确的二分法 | 二分查找法 | 二分搜索法 | LeetCode:704. 二分查找_哔哩哔哩_bilibiliz
一个5分钟的视频显然无法讲清楚一个概念,因此强烈推荐点击上方链接观看视频。视频中会详细阐明左右区间在不同开闭条件下,循环所需要的不同判定条件,并给出了不同开闭条件下完整的代码思路流程。
关键要点:区间合法
最重要的一点就是判断每次产生的新区间是否合法。仅需给出几个例子便可方便大伙理解:
双闭/双开:缩小到最小后,[1,1]这个区间显然合法,而(1,1)则不合法,因为没有一个大于1又小于1的数。前者可为left<=right,后者就只能是left<right了
半开半闭:与双开的情况类似,不存在[1,1)的情况。
个人疏漏:未在循环里直接定义中间值mid
while (left <= right) {
int mid = (left + right) / 2;//一开始犯傻了,还把mid定义写在循环外,导致if判定下有重复代码
if (target < nums[mid])
{
right = mid - 1;
}
else if (target > nums[mid])
{
left = mid + 1;
}
else return nums[mid];
}
return -1;
个人的编程水平较低,一开始在循环外声明了mid,还在两个if判断下给mid重新赋值,导致可读性不如上图中的内容,记下来引以为戒。
移除元素
数组中移除元素并不容易! | LeetCode:27. 移除元素_哔哩哔哩_bilibili
可以先用两个for循环的暴力解法解决该题目,进而通过视频了解双指针的解题方式,开拓思维。(这里的指针可以理解为两个箭头,并非实际意义上的指针)
关键要点
快慢指针,快指针是一个探测器(类比为落下苹果的大树),检测当前位置的元素是否需要移除,如果不需要移除,那就掉下一个苹果;慢指针为接收器(类比为收苹果的果农),一开始有一个盒子,只有苹果落入盒中,果农才会追加新的盒子。我们认定装有苹果的盒子的总数为数组大小
for (int fast = 0; fast < nums.size(); fast++) {
if (val != nums[fast]) {
nums[slow] = nums[fast];
slow++;
}
}
return slow;
}
个人解惑:slow++不会导致多一位吗?
因为一开始指示数组位置时slow的初值为0,指向第一个元素,而我们最后通过slow要找的是数组大小,所以每个循环末尾的slow++不是问题。
假设 nums
是 [3, 2, 2, 3]
,val
是 3
。
- 初始时,
fast
和slow
都是 0。 fast
= 0,nums[fast]
= 3, 因为nums[fast]
等于val
,所以slow
不动。fast
= 1,nums[fast]
= 2, 因为nums[fast]
不等于val
,所以nums[slow]
变为 2,slow
移动到 1。fast
= 2,nums[fast]
= 2, 因为nums[fast]
不等于val
,所以nums[slow]
变为 2,slow
移动到 2。fast
= 3,nums[fast]
= 3, 因为nums[fast]
等于val
,所以slow
不动。
最后返回的数组大小为2。