一、二分法(有序数组)
1、搜索等于target的元素
法一:
直接遍历
cpp
class Solution {
public:
int search(vector<int>& nums, int target) {
int i=0;
for(i=0;i<nums.size();i++){
if(nums[i]==target){
return i;
}
}
return -1;
}
};
法二:
二分查找(前提:数组已经是升序排序)
1、设left、right、middle
2、让target和nums[middle]比较,分类讨论
3、移动左边界或右边界
cpp
class Solution{
public:
int search(vector<int>& nums, int target) {
int left=0,right=nums.size()-1; //1 设置左、右、中间变量int middle=(left+right)/2
while(left<=right){
int middle=(left+right)/2;
if(target<nums[middle]){ //2 target与中间值比较并分类讨论:比中间值大还是小还是相等
right=middle-1; //target偏小则right左移
}
else if(target>nums[middle]){
left=middle+1; //target偏大则left右移
}
else{
return middle; //相等则返回当前下标middle
}
}
return -1;
}
};
注意:如果是[ ],则
1、左右边界初始值:left=0,right=nums.size()-1
2、循环条件:while(left<=right) left==right时[left,right]仍有意义
3、移动边界:因为已经明确nums[middle]不等于target,所以应让left=middle+1,right=middle-1
如果是[ ),则
1、左右边界初始值:left=0,right=nums.size()
2、循环条件:while(left<right) left==right时[left,right)没有意义
3、移动边界:因为已经明确nums[middle]不等于target,所以应让left=middle+1,right=middle
2、搜索等于target的元素或target的插入位置
有序数组,可以使用二分法
cpp
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
int left=0,right=nums.size()-1;
while(left<=right){
int middle=(left+right)/2;
if(target==nums[middle]){
return middle;
}
else if(target<nums[middle]){
right=middle-1;
}
else{
left=middle+1;
}
}
return left; //找不到目标值则返回插入位置,经推算插入位置就是left
}
};
注意:如果找不到等于target的值,则要考虑三种插入情况
插入在数组之前、数组之后、数组之中
举个最简单的例子来推算:比如[0],left=right=middle=0
target=-100时,right左移,最终right=-1,left=0,而插入位置是0
target=100时,left右移,最终left=1,right=0,而插入位置是1
综上,猜测插入位置就是left0
再看[0,4],target=3时,插入位置也是left
或者直接想,最终状态是nums[right],target,nums[left],所以把target插在left的位置
二、双指针原地操作数组
1、移除等于val的元素
法一: 双指针法
i遍历整个数组,res记录保留下来的数组,都在原地操作
cpp
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int res=0;
for(int i=0;i<nums.size();i++){
if(nums[i]!=val){ //如果不等于val,则保留该数组元素(记录下来,在原地数组)
nums[res++]=nums[i];
}
}
return res;
}
};
法二:有出错的先让后面的来找补
cpp
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
//如果前面有等于val的值,则用后面的值来替补
int left=0,right=nums.size()-1;
while(left<=right){
if(nums[left]==val){ //nums[left]等于val,则让nums[right]来替补(有出错的先让后面的来找补)
nums[left]=nums[right--];
}
else{
left++; //nums[left]不等于val,则left继续前行
}
}
return left;
}
};
2、移除重复项
cpp
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
int res=0;
for(int i=0;i<nums.size();i++){
if(i==0||nums[i]!=nums[i-1]){ //如果当前元素不等于前一个元素,说明无重复,录入
//(注意:讨论没有前一个元素的情况)
nums[res++]=nums[i];
}
}
return res;
}
};