27 移除元素
双指针法,设定两个指针,快指针用来从左到右进行遍历,慢指针用来记录需要覆盖的元素,当快指针发现不等于目标值的元素时,将该元素赋值给慢指针所在的元素位置。
注意:快慢指针均为从0开始,假设数组第一个元素不为目标值,赋值情况为
nums[0]->nums[0],之后快慢指针均指向1。
704 二分查找
熟悉左闭右开和左闭右闭的二分法即可。
35 搜索插入位置
这题同理,用左闭右闭二分法进行解题
第一种情况:数组中存在目标值:返回目标值所在的位置。
第二种情况:数组中不存在目标值:此时left和right相邻,且nums[left]<target<nums[right]。
此时返回目标值应该插入的位置,即left(超越第二名,你就是第二名)。
34 在排序数组
这题存在重复元素,需要寻找元素最先出现的位置和最后出现的位置。比较简单的思路是先用常规二分法找到一个位置(记为mid)然后对mid分割出来的两个区间分别二分,用来找到最先出现的位置(first)和最后出现的位置(end)
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
int l=0;
int r=nums.size()-1;
int first=-1;//最先出现的位置
int end=-1;//最后出现的位置
while(l<=r)//寻找first
{
int mid=(r-l)/2+l;
if(target<nums[mid])
r=mid-1;
else if(target>nums[mid])
l=mid+1;
else//此时target=nums[mid]这时候将边界设置为(l,mid-1),
//确保如果在mid之前有相同的目标值也能被找到。
//由于mid位置的值已经确定与目标值相同,所以只考虑mid左边的值
{
r=mid-1;
first=mid;
}
}
l=0;
r=nums.size()-1;
while(l<=r)
{
int mid=(r-l)/2+l;
if(target<nums[mid])
r=mid-1;
else if(target>nums[mid])
l=mid+1;
else
{
l=mid+1;
end=mid;
}
}
return {first,end};
}
};
以极端情况数组[7,7,7,7,7,7,7,7,7],目标值为7进行推导
寻找first:开始时:l=0,r=8;
第一次循环:mid=4,此时nums[4]==7,r=4-1=3,first=4
第二次循环:mid=(3+0)/2=1,此时nums[1]==7,r=-1-1=0;first=1
第三次循环:mid=(0+0)/2=0,此时nums[0]==7,r=0-1=-1;first=0
不满足循环条件,循环结束,输出first=0
注意,此处将first的循环嵌套在常规的二分法中可以一直循环(可能不止两次循环),直到确定边界值为止