代码随想录算法训练营第一天(LeetCode704二分查找、27移除元素)

704:二分查找

思想:通过不断缩小区间范围来搜索target

注意事项:注意区间范围

        如果是[left,right]区间的话,需要判断left和right下标对应的值是否满足条件,因此初始的时候left=0,right=len-1,每次二分的时候找left和right的中间下标index,如果target比nums[index]小,right-1,如果比nums[index]大,left+1,如果等于的话说明找到了下标,直接return就行。左右都是闭区间的话,left==right是有意义的,所以得是while (left <= right)。例如数组只有一个元素5,target=5,那么只有while (left <= right)时才能进入循环。

        如果是[left,right)的话,初始条件right=len,而不是len-1,右边的开区间,因此每次更新的时候right不需要减1,left==right也是没有意义的,因此直接是while (left < right)

具体实现:i表示左边,j表示右边,index的中点,res是返回值

代码:

1、左闭右闭

class Solution {
    public int search(int[] nums, int target) {
        int len = nums.length;
        int i = 0, j = len-1, res = -1;
        
        while(i<=j){
            int index = (j+i)/2;
            if(target<nums[index]){
                j = index - 1;
            }else if(target>nums[index]){
                i = index + 1;
            }else{
                res = index;
                break;
            }
        }
        return res;
    }
}

2、左闭右开

class Solution {
    public int search(int[] nums, int target) {
        int len = nums.length;
        int i = 0, j = len, res = -1;
        
        while(i<j){
            int index = (i+j)/2;
            if(target<nums[index]){
                j = index;
            }else if(target>nums[index]){
                i = index + 1;
            }else{
                res = index;
                break;
            }
        }
        return res;
    }
}

35:搜索插入位置

思想:利用二分法的思想使得时间复杂度为O(logn)

关键:找到的话直接返回数组下标,如果没找到的话“返回它将会被按顺序插入的位置”。对于左闭右闭的情况,循环结束的条件要么是找到了下标,如果没找到下标的话就是left=right+1,left所处的小标就应该是target按顺序应该插入的位置,所以应该return left。对于左闭右开的情况下,如果没找到下标,要么left=right+1或者left=right,所以还是返回left位置。

代码:

class Solution {
    public int searchInsert(int[] nums, int target) {
        int len = nums.length;
        int left = 0, right = len - 1;
        while(left<=right){
            int index = (left + right)/2;
            if(target<nums[index]){
                right = index - 1;
            }else if(target>nums[index]){
                left = index + 1;
            }else{
                return index;
            }
        }

        return left;
    }
}

34:在排序数组中查找元素的第一个位置和最后一个位置

方法:在二分法查找的基础上,先找到元素所在的位置,然后再通过左右滑动查找左边界和右边界。

代码:

class Solution {
    public int[] searchRange(int[] nums, int target) {
        int len = nums.length;
        int left = 0, right = len - 1;
        int[] res = {-1,-1};
        while(left<=right){
            int index = (left + right)/2;
            if(target<nums[index]){
                right = index - 1;
            }else if(target>nums[index]){
                left = index + 1;
            }else{
                for(int i =index;i>=left;i--){
                    if(nums[i]!=target){
                        res[0] = i+1;
                        break;
                    }else{
                        res[0] = left;
                    }
                }
                for(int j=index;j<=right;j++){
                    if(nums[j]!=target){
                        res[1] = j-1;
                        break;
                    }else{
                        res[1] = right;
                    }
                }
                break;
            }
        }
        return res;
    }
}

27:移除元素

思想:双指针法:通过快指针和慢指针把不等于val的元素往前靠。筛选掉val,val的位置空出来,就可以插入后面的值。

代码:

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

今日感想:

算法思路理解和代码实现还是有一定区别的,再理清算法思路的基础上,代码实现还需要考虑更多的细节。
 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值