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

LeetCode 704

题目链接: 704.二分查找

想要弄明白二分查找法,就要处理好两个边界:

//第一个边界,while循环里我们应该用 < 还是 <= 呢
while(left <= right)
while(left < right)
//第二个边界,当 target  < nums[middle]时,我们调整 right 时用 middle 还是 middle - 1
if(target < nums[middle])
	right = middle;
	right = middle - 1;

当我们一开始确定好数组边界之后,就不要去改变这个边界,在后边处理时一直保持就好了。总结,就是下边一句话:

区间不变量,要在二分查找的过程中,保持不变量。


接下来先采用左闭右闭(其实就是,left和right下标都指向数组中的元素)写法讲解:
左闭:left = 0
右闭:right = nums.length - 1
在这里插入图片描述
这种情况下:while循环里 left 是可以 等于 right 的,因为它们都是指向数组里存在的元素。

while(left <= right)

现在采用左闭右开(这个时候right就不指向,数组内的元素了):
在这里插入图片描述
左闭:left = 0
右开:right = nums.length
我们可以看到,right指向了数组外边。所以,采用二分查找时 left 不能等于 right (因为 right 不指向数组中的元素)

while( left < right)

接下来处理第二个边界:
在这里插入图片描述
target < nums[middle]时,我们要调整 right 。
我们采用右闭区间时:
right要指向,下次查找区间内。middle已经判断过了,所以不在下次查找区间内。

right = mid - 1;//所以,调整 right = middle - 1;

我们采用右开区间时:
right要指向,下次查找区间外边。middle已经判断过了,所以 middle 在下次查找区间外。

right = mid;//所以,调整 right = middle;

(左闭右闭类):

class Solution {
    public int search(int[] nums, int target) {
        int left= 0,right= nums.length - 1,mid = 0;
        while(left <= right){
            mid = left + ((right - left) >> 1);//防止两个int型相加溢出,这行代码含义是 小的数 加上 与大数的差值的一半。就是两数相加除以二。
            if(nums[mid] < target){
                left = mid + 1;
            }else if(nums[mid] > target){
                right = mid - 1;
            }else if(nums[mid] == target){
                return mid;
            }
        }
        return -1;
    }
}

27.移除元素

在本子上画了一遍大概过程,按着过程经过几次错误之后,两层循环解出来了。

class Solution {
    public int removeElement(int[] nums, int val) {
        int size = nums.length;
        for(int i = 0; i < size;i++){
            if(nums[i] == val){
                for(int j = i +1;j<size;j++){
                    nums[j-1] = nums[j];
                }
                i--;
                size--;
            }
        }
        return size;
    }
}

其中i--是因为你把后边的数字往前提了,循环最后会i++这样的话我们会跳过刚移到前边覆盖位置的元素,没有判断。所以,要i--。有人疑惑如果第一个就是要移除的值i--使下一轮i = -1。不会因为在本次循环结束会i++。所以,下一轮开始依旧是i = 0


在看完代码随想录的解法,感觉好神奇。因为,题目不要求移除完的数组还是按照以前的顺序。所以可以用快慢指针法。

快慢指针法

代码如下:

class Solution {
    public int removeElement(int[] nums, int val) {
    int size = nums.length, fastIndex = 0,slowIndex = 0;
    for(;fastIndex <nums.length ;fastIndex++){
        if(val != nums[fastIndex]){
            nums[slowIndex] = nums[fastIndex];
            slowIndex++;
        }
    }
    return slowIndex;
    }
}

这个方法的大概过程是,当有要消除的值slowIndex会慢1个位置,当fastIndex走到最后时,slow的位置就是剩余的数组元素的个数。有目标元素的话就把后边的非目标元素换上去。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值