代码随想录算法训练营day01| 704. 二分查找,27. 移除元素。

● 题目链接

704. 二分查找:https://leetcode.cn/problems/binary-search/

● 思路:指针法

● 难点:理解区间左闭右开与左闭右闭

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

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

    输入: nums = [-1,0,3,5,9,12], target = 2
    输出: -1
    解释: 2 不存在 nums 中因此返回 -1
 */
public class BinarySearch {
    public static void main(String[] args) {
        int[] nums = {-1,0,3,5,9,12};
        int[] nums2 = {-1,0,3,5,9,12};
        System.out.println(new BinarySearch().binarySearch(nums, 9));
        System.out.println(new BinarySearch().binarySearch2(nums2, 2));
    }

    /**
     * 二分查找
     * ver1:[left,right]左闭右闭区间
     * @param nums   目标数组
     * @param target 目标值
     * @return 目标值在数组中的下标,找不到返回-1
     */
    public int binarySearch(int[] nums, int target) {
        int left = 0;
        int right = nums.length - 1;
        // 左闭右闭区间,left=right是有意义的
        while (left <= right) {
            int mid = left + (right - left) / 2;
            if (target < nums[mid]) {
                // 目标值在左半边,更新右边界
                right = mid - 1;
            }else if(target > nums[mid]){
                // 目标值在右半边,更新左边界
                left = mid + 1;
            }else if(target == nums[mid]){
                return mid;

            }
        }
        // 未找到
        return -1;
    }

    /**
     * 二分查找
     * ver2:[left,right)左闭右开区间
     * @param nums   目标数组
     * @param target 目标值
     * @return 目标值在数组中的下标,找不到返回-1
     */
    public int binarySearch2(int[] nums, int target) {
        int left = 0;
        int right = nums.length;
        // 左闭右开区间,left = right无意义
        while (left < right) {
            int mid = left + (right - left) / 2;
            if (target < nums[mid]) {
                // 目标值在左半边,更新右边界
                // 左闭右开区间,此时target仍有可能等于nums[mid]
                right = mid;
            }else if(target > nums[mid]){
                // 目标值在右半边,更新左边界
                // target不可能等于nums[mid]
                left = mid + 1;
            }else if(target == nums[mid]){
                return mid;
            }
        }
        // 未找到
        return -1;
    }
}

27. 移除元素:https://leetcode.cn/problems/remove-element/

● 思路:暴力解法,快慢指针

● 难点:暴力解法中的指针回退,掌握快慢指针的使用

package day01;

/*
    27. 移除元素
    给你一个数组 nums 和一个值 val,
    原地移除所有数值等于 val 的元素,并返回移除后数组的新长度。
    不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并原地修改输入数组。
    元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

    示例 1: 给定 nums = [3,2,2,3], val = 3, 函数应该返回新的长度 2,
     并且 nums 中的前两个元素均为 2。 你不需要考虑数组中超出新长度后面的元素。

    示例 2: 给定 nums = [0,1,2,2,3,0,4,2], val = 2, 函数应该返回新的长度 5,
    并且 nums 中的前五个元素为 0, 1, 3, 0, 4。
 */
public class RemoveElem {
    public static void main(String[] args) {
        int[] nums = {3, 2, 2, 3};
        int[] nums2 = {0, 1, 2, 2, 3, 0, 4, 2};

        System.out.println(new RemoveElem().removeElem2(nums, 3));
        System.out.println(new RemoveElem().removeElem2(nums2, 2));
    }

    /**
     * 移除元素
     * ver2:双指针法
     *
     * @param nums 目标数组
     * @param val  要移除的元素
     * @return 修改后数组的长度
     */
    public int removeElem2(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;
    }

    /**
     * 移除元素
     * ver1:暴力解法(两次循环)
     *
     * @param nums 目标数组
     * @param val  要移除的元素
     * @return 修改后数组的长度
     */
    public int removeElem(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指针回退
                i--;
                // 数组长度-1
                size--;
            }
        }
        return size;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值