二分查找,对应的场景是:有序数组,且无重复元素
如果有重复元素二分查找的返回值将不止一个
一开始用的递归,感觉没救了。。。
class Solution {
public:
void halfSearch(int startIndx,int endIndx,vector<int>& nums,int target,int &indx){
if(startIndx < 0 || endIndx >= nums.size() || endIndx < startIndx){
return;
}
int midIndx = (endIndx - startIndx) * 0.5 + startIndx;
if(nums[midIndx] == target){
indx = midIndx;
return;
}
if(nums[midIndx] > target){
halfSearch(startIndx,midIndx-1,nums,target,indx);
}
if(nums[midIndx] < target){
halfSearch(midIndx+1,endIndx,nums,target,indx);
}
}
int search(vector<int>& nums, int target) {
int startIndx = 0;
int endIndx = nums.size()-1;
int indx = -1;
halfSearch(startIndx,endIndx,nums,target,indx);
return indx;
}
};
附上左闭右闭区间的二分法
class Solution {
public:
int search(vector<int>& nums, int target) {
int left = 0;
int right = nums.size() -1;
while(left <= right){
int mid = (right - left) *0.5 + left;
if(nums[mid] == target){
return mid;
}
if(nums[mid] > target){
right = mid - 1;
}
if(nums[mid] < target){
left = mid + 1;
}
}
return -1;
}
};
附上左闭右开区间的二分法
class Solution {
public:
int search(vector<int>& nums, int target) {
int left = 0;
int right = nums.size();
while(left < right){
int mid = (right - left) *0.5 + left;
if(nums[mid] == target){
return mid;
}
if(nums[mid] > target){
right = mid ;
}
if(nums[mid] < target){
left = mid + 1;
}
}
return -1;
}
};
这里二分法的左闭右开和左闭右闭区间一经选定,就要严格执行,也就是说,nums[right]是无效的临界位置数据
像这类型数组原地修改的问题,都可以考虑使用双指针的处理,这里使用到的是双指针的快慢指针来做
所谓的快慢指针,我的理解其实就是
- 快指针 fast 用于遍历读取新元素
- 慢指针 slow 用于对fast遍历到的合格元素进行确认,也就是说,slow指针用于维护一个[0,slow]的合格元素区间,确认处于这个区间下的都是合格的元素
- 当然,数组可以用下标索引来替代指针指向元素
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int slow = -1;
for(int fast = 0;fast < nums.size();fast++){
if(nums[fast] != val){
nums[++slow] = nums[fast];
}
}
return slow+1;
}
};
slow指针初始时没有获取到合格元素,等待fast不断遍历数组新元素,每当fast找到一个符合题意的合格元素时,slow后移,并且把合格元素纳入下标[0,slow]区间
当然,暴力循环的方法也是可以的,但是相比双指针法快慢指针在一个for循环中同时处理,暴力解中嵌套的循环带来很大的时间开销
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int valSum = 0;
for(int i = 0;i < nums.size()-valSum;i++){
if(nums[i] == val){
valSum++;
for(int j = i;j < nums.size()-valSum;j++){
nums[j] = nums[j+1];
}
i--;
}
}
return nums.size() - valSum;
}
};