代码随想录算法训练营第一天 | 704.二分查找 27.移除元素

704.二分查找

1.左闭右闭

思路:left表示数组的第一个元素的下标,right表示数组的最后一个元素的下标,mid代表数组的中间元素的下标,如果arr[mid]<val(val表示要查找的值),那么left=mid+1;如果arr[mid]>val(val表示要查找的值),那么right=mid-1;如果arr[mid]==val,则返回mid的值。

注意,循环条件是left<=right,因为是左左闭右闭,所以如果left==right,就表示一个元素,这时也能查找,除非left>right,说明已经没有元素了。

2.左闭右开

跟左闭右闭的唯一区别是,因为是右开,所以最右边的元素是取不到的,所以最开始初始化right=nums.size(),同时,因为是右开,所以循环条件是left<right,因为left<right说明有超过1的元素个数,如果left>=right,是没有元素的,还要注意,如果arr[mid]>val(val表示要查找的值),那么right-1,那么right=mid,因为右边是取不到的,所以如果right=mid-1,就取不到mid左边的元素了

class Solution {
public:
    int search(vector<int>& nums, int target)
    {
     //左闭右闭
    //     int left = 0;
    //     int right = nums.size() - 1;
    //     while (left <= right)
    //     {
    //         int middle = left + (right - left) / 2;
    //         if (nums[middle] > target)
    //         {
    //             right = middle - 1;
    //         }
    //         else if (nums[middle] < target)
    //         {
    //             left= middle + 1;
    //         }
    //         else
    //         {
    //             return middle;
    //         }
    //     }
    //     return -1;
    // }
    //左闭右开
        int left = 0;
    int right = nums.size() ;
    while (left < right)
    {
        int middle = left + (right - left) / 2;
        if (nums[middle] > target)
        {
            right = middle;
        }
        else if (nums[middle] < target)
        {
            left= middle + 1;
        }
        else
        {
            return middle;
        }
    }
    return -1;
}
};

27.移除元素

1.暴力解

直接来一个for循环遍历数组的所有元素,如果找到了要移除的元素,则将这个元素后面的元素依次覆盖前面的元素,即把它们一个个往前挪动。

2.双指针1(难)

设置pre=0;cur=0;将cur遍历,如果arr[i]!=val(要查找的值),那么arr[pre++]=arr[cur],即pre++,表示pre会往后面移动一位,如果arr[i]==val,那么只有cur移动,pre还在原来的位置,cur不断++,直到找到不是val的值,那么将该值赋值给pre所在的位置,这时候pre才可以继续往前移动,达到将不是val的值不断往前移动,实现覆盖的效果。

3.双指针2(难)

设置left=0;right=nums.size()-1;如果left<=right(注意,这里=是考虑如果left>right,因为left是一个一个动的,所以这时候left肯定在right的右边,那么这是left代表的就是数组的长度)&&arr[left]!=val,那么left可以不断往右移动,直到找到对应的val值,这时候,右边的指针(并不是指针,只是个比喻)right就可以开始移动了,只要它所指的值不是val,那么就可以不用移动,直接把这个值赋值给被删除元素的位置,然后right--就实现了把最右边不是val的值赋值给val原本所在的位置,并且这时候又会实现长度自动减一的结果;如果它所指的值是val,那么肯定要往左边移动,因为val本来就是要被删除的,right--其实就实现了删除右边多余的val的值。

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;
//     }

//双指针
// int pre=0;
// for(int i=0;i<nums.size();i++)
// {
//     if(nums[i]!=val)
//     {
//         nums[pre++]=nums[i];
//     }
// }
// return pre;
//     }

//双向指针
int left=0;
int right=nums.size()-1;
while(left<=right)
{
    while(left<=right&&nums[left]!=val)
    left++;
    while(left<=right&&nums[right]==val)
    right--;
    if(left<right)
    {
        nums[left++]=nums[right--];
    }
}
return left;
}
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值