Leetcode704.二分查找
题目链接
关键词:二分查找 循环不变量 区间
问题思路:二分查找的应用,关键在于循环过程中区间的维护,记住循环不变量原则,在这个问题中循环不变量是区间的定义,注意左闭右开和左开右闭的区别
class Solution {
public:
int search(vector<int>& nums, int target) {
int left = 0, right = nums.size();
while (left < right) {
int middle = (left + right) / 2;
if (nums[middle] == target) return middle;
else {
if (nums[middle] > target) {
right = middle;
}
else left = middle + 1;
}
}
return -1;
}
};
在初始化left与right变量时就应该想清楚区间的定义是什么,如上采用左闭右开
class Solution {
public:
int search(vector<int>& nums, int target) {
int left = 0, right = nums.size() - 1;
while (left <= right) {
int middle = (left + right) / 2;
if (nums[middle] == target) return middle;
else {
if (nums[middle] > target) {
right = middle - 1;
}
else left = middle + 1;
}
}
return -1;
}
};
如上采用左闭右闭
在处理问题的过程中考虑到一个问题
middle = (left + right)/ 2 与 middle = (right - left)/ 2 + left 是完全等价的吗?
作一个简单证明(取整函数性质的应用):
反思:该题我们成功处理了查找某个特定值的位置,那么如果题目要求的是查找第一个大于target的数组元素的下标,我们又当如何处理?换言之,如何寻找符合题目要求的下标范围?
Leetcode27.移除元素
题目链接
关键词:双指针
问题思路:我们需要找到所有目标元素,同时将目标元素移动到数组末尾,考虑一次遍历解决问题,那么不可避免需要第二个指针指向数组末尾记录新数组的末尾下标,自然想到双指针算法。双指针算法使得遍历的终止条件由单指针抵达数组末尾变为两个指针发生碰撞。换言之,一般的遍历不过是一个指针不会移动情况下的双指针。
双指针算法理解参考文章
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int left = 0, right = nums.size() - 1;
while (left <= right) {
if (nums[left] == val) {
int temp = nums[left];
nums[left] = nums[right];
nums[right] = temp;
--right;
}
else {
++left;
}
}
return right + 1;
}
};
反思:对于双指针算法,我们还有很多需要熟练的地方,双指针算法的目的是优化算法的时间复杂度,其原理在于两个指针移动方向的单调性,双指针移动不存在回溯
今日学习时长:3h