day1力扣704 二分查找、力扣27 移除元素、力扣977 有序数组的平方

704.二分查找 

文章链接: 代码随想录

这道题目是二分查找思想。 主要是代码要写的简洁,不冗余。 注意要点:

1.对于左闭右闭区间,和左闭右开区间2种方式, 考虑边界问题。 

左闭右闭区间时候,更新left或者right,都是+1,或者-1,直接考虑边界。 

代码如下:

class Solution {
    public int search(int[] nums, int target) {
        int left=0;
        int right =nums.length-1;
        while(left<=right){
             int middle = left+(right-left)/2;
            if(target== nums[middle]){
                return  middle;
            }else if( target >nums[middle]){
                left =middle+1;
            }else{
                right =middle-1;
            }
        }
        //这个条件下不满足,就是没有找到目标
        return -1 ;
        
    }
}

左闭右开区间时候,更新left时候,仍然是+1,但是更新right,不能-1,因为我们的逻辑是                [left ,right),并且 我们定义int right =nums.length,不能-1  

代码如下:

class Solution {
    public int search(int[] nums, int target) {
        int left=0;
        int right =nums.length;
        while(left<right){
             int middle = left+(right-left)/2;
            if(target== nums[middle]){
                return  middle;
            }else if( target >nums[middle]){
                left =middle+1;
            }else{
                right =middle;
            }
        }
        //这个条件下不满足,就是没有找到目标
        return -1 ;
        
    }
}

2.考虑代码的简洁性,不能把middle 的更新放到多个if else判断分支中去。

只需要在while 循环体开始定义就行。 

如下冗余:

class Solution {
    public int search(int[] nums, int target) {
        int left=0;
        int right =nums.length;
        int middle = left+(right-left)/2;
        while(left<right){
            if(target== nums[middle]){
                return  middle;
            }else if( target >nums[middle]){
                left =middle+1;
                middle = left+(right-left)/2;
            }else{
                right =middle;
               middle = left+(right-left)/2;
            }
        }
        //这个条件下不满足,就是没有找到目标
        return -1 ;
        
    }
}

35.搜索插入位置 

这里考虑的是left>right,当循环结束后, left指向的元素始终是大于等于target的候选位置,这是target应该插入的位置

right指向的元素始终小于target 。

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

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

这道题目的方法和二分查找差不多,重要的是返回多个目标值,需要多一步循环迭代,找到目标值的起点和终点, 用while循环迭代便可。 代码如下:

class Solution {
    public int[] searchRange(int[] nums, int target) {
        int [] dos  = new int []{-1,-1}; 
        if (nums.length == 0 || target < nums[0] || target > nums[nums.length - 1]) {
            return dos;
        }
        int left =0;
        int right =nums.length-1;
        while (left <= right){
            int middle = left + ((right - left) >> 1);
            if (target >nums[middle]){
                left =middle +1;
            }else if (target <nums[middle]){
                right =middle -1;
            }else{
                int start=middle ;
                
                while(start >0  && nums[start-1]==target ){
                    start--;
                }
                int end =middle ;
                while (end <nums.length-1 &&target ==nums[middle] && nums[end+1]==target  ){
                    end++;
                }
                dos[0]=start;
                dos[1]=end;
                return dos;  
            }
        }
        return dos;  
    }
}

27.移除元素 

如果用暴力解法的话, 就是从nums数组中找到第一个属于val的位置,nums[i] =val ; 然后对i+1 的位置以及之后的数据进行前移动:

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

这道题用双指针的方式去写。 其中最重要的是要理解fast指针寻找新数组的数,不属于新数组的数,就会自动跳过。 slow指针是记录新数组的下标,所以slow是一步步迭代。 这样就能做到把fast找到的的值逐个放到slow迭代次序的数组中去。  完成非目标val数据的向前移动和覆盖,实现删除元素的目的。 

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

977.有序数组的平方

这道题的得排大小, 注意原始数组是非降序排序,所以它的最大值一定是左侧或者右侧。 那么我们设定一个新的数组,往里面填充值。首先拿最左侧和最右侧的值(经过平方后的值)来比较,最大的放在新数组的最后一个位置,并且把新数组的索引位置向前移动一个。 

同时要判断到底是左侧大的,or右侧大的,如果是左侧大的,left++,移动左侧, 反之,移动right--  

class Solution {
    public int[] sortedSquares(int[] nums) {
        int [] result =new int [nums.length];
        int pos = nums.length-1;
        int left =0 ;
        int right =nums.length-1;
        while(left<=right){
            if(nums[left]*nums[left]> nums[right]*nums[right]){
                result[pos] =nums[left]*nums[left];
                left++;
            }else{
                result[pos]=nums[right]*nums[right];
                right--;
            }
            pos--;
        }
        return result;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值