LeetCode704.二分查找
题目链接:704.二分查找
思路:使用二分查找下标的前提是元素有序和无重复值,因为一旦有重复元素,使用二分查找法返回的元素下标可能不是唯一的。
遇到的难点:
- 什么时候跳出while循环
- left是等于middle+1还是middle,right同理
C++代码
class Solution {
public:
int search(vector<int>& nums, int target) {
// 1.元素有序(升序)
// 2.返回下标
// 左闭右闭
int len = nums.size();
int left = 0, right = len -1;
while(left <= right) {
int middle = (left + right) / 2;
if (nums[middle] < target) left = middle + 1;
else if (nums[middle] > target) right = middle -1;
else return middle;
}
return -1;
}
};
class Solution {
public:
int search(vector<int>& nums, int target) {
// 左闭右开
int left = 0;
int right = nums.size();
while(left < right) {
int middle = left + ((right - left) >> 1);
if (nums[middle] < target) left = middle + 1;
else if (nums[middle] > target) right = middle;
else return middle;
}
return -1;
}
};
本题收获
- 对于
while (letf < right)
还是写while (left < right)
是对区间的定义的两种结果,第一种是区间为左闭右开[letf, right)
,第二种是区间左闭右闭[left,right]
。因此二分有两种写法 - 针对两种写法,改变的是right的每次循环取值。当区间为左闭右开时,右值每次都取不到,所以
right = middle
;当区间为左闭右闭时,右值索引会被middle取到,所以right = middle - 1
LeetCode27.移除元素
题目链接:27.移除元素
思路:首先题目要求原地移除所有数值等于val
的元素,且返回移除后数组的长度。不能开辟新的数组用于存放移除元素后的数组,那只能移动所有数值等于val的元素到原数组的末端。
遇到的难点:
- 如何维护修改后数组的长度
C++代码
快慢指针法
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int slowIndex = 0;
for (int fastIndex = 0; fastIndex < nums.size(); fastIndex ++) {
if (nums[fastIndex] != val) nums[slowIndex ++] = nums[fastIndex];
}
return slowIndex;
}
};
暴力解法
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int size = nums.size();
for (int i = 0; i < size; i ++) {
if (nums[i] == val){
for (int j = i + 1; j < nums.size(); j ++) {
nums[j - 1] = nums[j];
}
i --;
size --;
}
}
return size;
}
};
本题收获
- 快慢指针的指针各有不同的性质,快指针用于寻找新数组的元素 ,新数组就是不含有目标元素的数组,慢指针用于指向更新,新数组下标的位置。
- 巧妙的是慢指针的值刚好等于数组移除元素后的长度,我个人理解为慢指针遍历完了所有更新的下标,最后指向移除元素数组的末端+1,形成左闭右开区间。