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

LeetCode704 力扣

* 基础二分法

* 考虑如何不让数据溢出,区间如何切换

* LeetCode34 力扣寻找最左区间 和 最右区间,套路和基础二分法类似,就是要在找到target的时候继续向左或者向右移动

package algor.trainingcamp;

/**
 * @author lizhe
 * @version 1.0
 * @description: https://leetcode.cn/problems/binary-search/
 *
 * 二分法
 * @date 2023/4/5 09:45
 */
public class LeetCode704 {
    public int search(int[] nums, int target) {
        int left = 0;
        int right = nums.length - 1;

        while(left <= right){
            int mid = left + ((right - left) >> 1);

            if(nums[mid] < target){
                //值偏小,向右取
                left = mid + 1;
            }else if(nums[mid] > target){
                //偏大,向左取
                right = mid - 1;
            }else{
                return mid;
            }
        }

        return -1;
    }

    /**
     * 找到最左的含义是: 即便找到了目标值,还是需要继续向左寻找(right边界向左)
     */
    public int searchLeft(int[] nums, int target) {
        int left = 0;
        int right = nums.length - 1;

        while(left <= right){
            int mid = left + ((right - left) >> 1);

            if(nums[mid] < target){
                left = mid + 1;
            }else if(nums[mid] > target){
                right = mid - 1;
            }else{
                //即便target值相等 还是需要继续向左
                right = mid - 1;
            }
        }

        return left;
    }

    /**
     * 找到最右的含义是: 即便找到了目标值,还是需要继续向右寻找(left边界向右)
     */
    public int searchRight(int[] nums, int target) {
        int left = 0;
        int right = nums.length - 1;

        while(left <= right){
            int mid = left + ((right - left) >> 1);

            if(nums[mid] < target){
                left = mid + 1;
            }else if(nums[mid] > target){
                right = mid - 1;
            }else{
                left = mid + 1;
            }
        }

        return right;
    }

    public static void main(String[] args) {
        LeetCode704 demo = new LeetCode704();
        System.out.println(demo.search(new int[]{-1, 0,3, 5, 9, 12}, 3));
    }
}

LeetCode 27 力扣

1. 暴力解法: 外层循环遍历数组,如果发现出现需要替换的值,将后续的值均都往前赋值(本意是向前提一位,但是操作上是赋值,需要将末值进行忽略)

2. 双指针: 快指针遍历数组,找到无需移除的元素,慢指针原地更新

package algor.trainingcamp;

/**
 * @author lizhe
 * @version 1.0
 * @description: https://leetcode.cn/problems/remove-element/ 移除元素
 * @date 2023/4/5 10:17
 *
 */
public class LeetCode27 {
    /**
     * 1. 暴力做法,当发现存在目标值,将目标值后面的所有数都往前挪一位(需要注意每次数据的长度变化)
     */
    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--操作,这里简单做一下3,2,2,3的debug
                 * 由于在代码中做的是'赋值'操作,因此每一次需要对末尾的数进行忽略,使用'i--'进行忽略
                 * 3,2,2,3 -> 2,2,3,3-> 2,2,3,3(数组情况)
                 * 3,2,2,3 -> 2,2,3 -> 2,2(有效数据)
                 */
                i--;
                size--;
            }


        }

        return size;
    }

    /**
     * 双指针
     * 明确快慢指针的定义
     * fast: 寻找新数组的元素
     * slow: 遍历旧数组,实时生成新数组 新数组的范围[0, slow]
     */
    public int removeElement2(int[] nums, int val){
        int slow = 0;
        for(int fast = 0;fast < nums.length;fast++){
            if(nums[fast] != val){
                //实时刷新数组
                nums[slow++] = nums[fast];
            }
        }
        return slow;
    }

    public static void main(String[] args) {
        LeetCode27 demo = new LeetCode27();
        System.out.println(demo.removeElement2(new int[]{3,2,2,3}, 3));
    }
}

你可能感兴趣的:(LeetCode,算法,java,leetcode)