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

文章探讨了在LeetCode的704题中进行二分查找时,边界条件处理的重要性,特别是`while(left<=right)`与`while(left<right)`的区别,以及如何避免数组越界。同时,文章通过示例代码解释了不同区间选择对循环的影响。此外,文章还提到了LeetCode的27题,即移除元素的问题,指出了一种常见的暴力解法,并讨论了循环中的边界考虑。
摘要由CSDN通过智能技术生成

Leetcode 704二分查找

带着问题去做题:

看视频时,老师反复强调了两点,都是关于边界处理的问题:1.循环变量while(left<right)还是while(left<=right),对应那两种区间?
2.right=midle-1还是right=midle???
之前看的时候一直记得这个,但没有理解;

先上代码:

/*--------对应左闭右闭[left,right]这种情况-------------------*/
class Solution {
public:
    int binarySearch(vector<int>& nums, int target)
    {
        int left=0; 
        int right=nums.size()-1;
        int midle;
        int count=50;
        //左闭右闭既[0,size-1],这样可以取到right而不会越界
        /*        t         m             */
        /*[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]*/
        while(left<=right){
            midle=left+(right-left)/2;//???会不会出现midle+1而越界的情况呢?值得试一试
            cout<<"mid="<<midle<<";  left="<<left<<";  right="<<right<<endl;
           if(left==right)
            cout<<"-----left=right,mid="<<midle<<endl;
           if(target<nums[midle]){
                right=midle-1;
            }else if(target>nums[midle]){
                left=midle+1;
            }else if(target==nums[midle]){
                return midle;
            }
            count--;//怕调试的时候循环卡死,设置了一个count
            if(count<1){
                cout<<"------------gameover-----------"<<endl;
                break;
            }
        }
        return -1;
    }
    int search(vector<int>& nums, int target) {
        int ans=binarySearch(nums,target);
        return ans;
    }
};

如果左右区间的 开闭 确定下来了,就可以确定while里的循环,既
左闭右闭[left,right] 对应 while(left<=right),确定下来这个就可以确定左右边界怎么选,既left=midle+1,right=midle-1;

左闭右闭[left,right)对应 while(left<right);
接下来就可以确定,

之前一直没仔细看,如何定义开闭区间
以下面这个数组为例:
假设它叫nums:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
常见的三种情况 左闭右闭[left,right],左闭右开[left,right), 左开右闭(] 一般这种情况比较少.
左闭右闭则left=0,right=20;
左闭右开left=0, ** right=21;** 这里right是超出数组的;

下面来测试一下,如果不按这样写会出现什么情况:

1.令left<=right,left=midle,right=midle;

        ........
		int right=nums.size()-1;
		cout<<"target="<<target<<endl;
		........
        /*        l         m         r   */
        /*[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]*/
        while(left<=right){
            midle=left+(right-left)/2;//???会不会出现midle+1而越界的情况呢?值得试一试
            cout<<"l="<<left<<" ;  mid="<<midle<<";  r="<<right<<endl;
           if(left==right)
            cout<<endl<<"-left=right,mid="<<midle<<endl;
           if(target<nums[midle]){
                right=midle;
            }else if(target>nums[midle]){
                left=midle;
            }else if(target==nums[midle]){
                return midle;
            }
            count--;
            if(count<1){
                cout<<"------------gameover-----------"<<endl;
                break;
            }

还是上面0-20的案例,发现末尾的元素20是取不到的,下面看看打印:
非常的恐怖,不加count就卡死 了

target=20;
l=0 ; mid=10; r=20
l=10 ; mid=15; r=20
l=15 ; mid=17; r=20
l=17 ; mid=18; r=20
l=18 ; mid=19; r=20
l=19 ; mid=19; r=20
l=19 ; mid=19; r=20
l=19 ; mid=19; r=20
l=19 ; mid=19; r=20
… …
l=19 ; mid=19; r=20
------------gameover-----------
-1

可以看到当运行到这里l=19 ; mid=19; r=20的时候,末尾的元素是取不到的;
2.令left<right,left=midle-1,right=midle+1;
省略代码:
同样也是取不到20

Leetcode27 移除元素

按照惯性的思维,自然就会想到用两个循环去解决它;
这里应该就是卡老师说的"暴力解法":

先上代码:

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int len=nums.size();
        for(int i=0;i<len;){
            /*--------------------------*/
            if(nums[i]==val){
           // cout<<"remove :"<<i<<" val:"<<val<<endl;
            for(int j=i;j<len;j++)
              {
                //当元素在末尾时
                if(j==len-1)
                {
                //cout<<"j=len-1;"<<endl  ;  
                 break;
                 }
                nums[j]=nums[j+1];//要防止i+1越界,万一i=len-1怎么办?
              }
            len--;
            continue;
            }
            i++;
        /*-------------------------------------*/
        }
        //cout<<endl<<"---len="<<len;
        return len;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值