Bootstrap

代码随想录算法训练营第一天 | 704.二分查找,27.移除元素 ,977.有序数组的平方

代码随想录算法训练营第一天 | 704.二分查找,27.移除元素 ,977.有序数组的平方

704.二分查找

给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1

示例 1:

输入: nums = [-1,0,3,5,9,12], target = 9
输出: 4
解释: 9 出现在 nums 中并且下标为 4

示例 2:

输入: nums = [-1,0,3,5,9,12], target = 2
输出: -1
解释: 2 不存在 nums 中因此返回 -1

1.左闭右闭

  • 明确区间为[left,right]。那么当while循环的时候就要判断left<=right是否有意义,当区间为[1,1]时,1<=1在区间范围内是有意义的(若是左闭右开[1,1),很明显右侧的1不包含在区间内部,所以1<=1是没有意义的);
  • 更新区间的时候if(nums[middle]>target)时,应该更新right,并且由于区间是闭的,很明确nums[middle]不在更新的区间内,所以right=middle-1;
  • 更新区间的时候if(nums[middle]<target)时,应该更新left,并且由于区间是闭的,很明确nums[middel]不在更新的区间内,所以left=middle+1。
class Solution {
    //左闭右闭
    public int search(int[] nums, int target) {
        int left = 0;
        int right = nums.length-1;
        if(target < nums[left] || target > nums[right]){
            return -1;
        }
        while(left <= right){
            int middle = (left + right)/2;
            if(target > nums[middle]){
                left = middle + 1;
            }else if(target < nums[middle]){
                right = middle - 1;
            }else{
                return middle;
            }
        }
        return -1;
    }
}

2.左闭右开

  • 明确区间为[left,right)。当while循环的时候就要判断left<=right是否有意义,这里无意义,所以应当是left<right;
  • 当更新区间的时候,if(nums[middle]>target),由于右开,本身right的值不在判断范围内而nums[middle]也不在更新的区间内,所以right=middle
  • if(nums[middle]<target),由于左闭,而nums[middle]本身不在更新的区间内,所以left=middle+1
class Solution {
    //左闭右开
    public int search(int[] nums, int target) {
        int left = 0;
        int right = nums.length;
        if(target < nums[left] || target > nums[right-1]){
            return -1;
        }
        while(left < right){
            int middle = (left + right)/2;
            if(target > nums[middle]){
                left = middle + 1;
            }else if(target < nums[middle]){
                right = middle;
            }else{
                return middle;
            }
        }
        return -1;
    }
}

注意:整个函数的返回值为int类型,因此一定要注意,函数的最后应当提供一个返回值。

27.移除元素

给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素。元素的顺序可能发生改变。然后返回 nums 中与 val 不同的元素的数量。

假设 nums 中不等于 val 的元素数量为 k,要通过此题,您需要执行以下操作:

  • 更改 nums 数组,使 nums 的前 k 个元素包含不等于 val 的元素。nums 的其余元素和 nums 的大小并不重要。
  • 返回 k

1.暴力求解

class Solution {
    public int removeElement(int[] nums, int val) {
        int size = nums.length-1;
        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+1;
    }
}

注意:这里的size存储的是数组的下标值,在这里最终返回的应当是数组的真实长度,所以为size+1.

2.双指针法

思想:用单个for循环实现双层for循环的操作。其中fast指针指向更新后的数组中的值,low指向要更新的数组中的位置。那么最后low返回的就是更新后数组的长度。

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

977.有序数组的平方

给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。

示例 1:

输入:nums = [-4,-1,0,3,10]
输出:[0,1,9,16,100]
解释:平方后,数组变为 [16,1,0,9,100]
排序后,数组变为 [0,1,9,16,100]

示例 2:

输入:nums = [-7,-3,2,3,11]
输出:[4,9,9,49,121]

思想:用双指针法请求,因为本身为非递减排序,也就是两端的元素值最大。所以直接用俩个指针从俩端比较出一个最大值,放在新的数组中即可。由于要求我们非递减排序,所以存储最大值的时候要从后往前进行存储。

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

注意:result[index–] = nums[right–]*nums[right–];这种写法,会导致第二次使用nums值的时候,下标已经发生改变,不是原先比较的值了。