Day1 二分查找+移除元素

文章介绍了二分查找算法的两种实现方式,分别对应左闭右闭和左闭右开区间,并分析了时间复杂度和空间复杂度。对于27.移除元素问题,提出了暴力法和快慢指针两种解决方案,同样关注了原地修改数组的限制和空间复杂度优化。
摘要由CSDN通过智能技术生成

Day1 二分查找+移除元素

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

704. 二分查找

题目链接:704.二分查找

思路:

数组元素为有序排列,我们需要确定搜索的左右边界。这道题中有边界可以包括也可以不包括,所有有两种[left, right]左闭右闭区间,他的while的循环条件left <= right,终止条件为 left == right + 1。 还有一种[left, right)左闭右开区间,他的while的循环条件left < right,终止条件为 left == right

代码部分:

方法一: 采用左闭右闭区间

class Solution {
    public int search(int[] nums, int target) {
        int left = 0;
        int right = nums.length - 1;
        // target在[left, right]
        while(left <= right){
            //int mid = (left + right) / 2;
            int mid = left + (right - left) / 2;
            if(nums[mid] < target){
            // 此时搜索区间为 [m + 1, r]
                left = mid + 1;
            }
            if(nums[mid] > target){
            // 此时搜索区间为 [l, m - 1]
                right = mid - 1;
            }
            if(nums[mid] == target){
                return mid;
            }
        }
        return -1;
    }
}

方法一: 采用左闭右开区间

class Solution {
    public int search(int[] nums, int target) {
        int left = 0;
        int right = nums.length - 1;
        // target在[left, right)
        while(left < right){
            //int mid = (left + right) / 2;
            int mid = left + (right - left) / 2;
            if(nums[mid] < target){
            // 此时搜索区间为 [m + 1, r)
                left = mid + 1;
            }
            if(nums[mid] > target){
            // 此时搜索区间为 [l, m)
                right = mid;
            }
            if(nums[mid] == target){
                return mid;
            }
        }
        return -1;
    }
}

两个算法时间复杂度:
O(log2n)
空间复杂度:
O(1)

27. 移除元素

题目链接:27.移除元素

思路:

因为题目要求不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并原地修改数组。所以有两种方法:
一:暴力法(两层循环,当找到要删除的值val时,把当前值val的后面所有元素往前移动一位)
二:快慢指针:
用慢指针保留去掉后的数组,慢指针从0开始;用快指针遍历数组。
---- 当数组元素不等于val时,把快指针对应值nums[fast]赋给慢指针nums[slow]
---- 当数组元素等于val时,不赋值,找下一个元素比较。

代码部分:

方法一:暴力法

class Solution {
    public int removeElement(int[] nums, int val) {
        int len = nums.length;
        for(int i = 0; i < len; i++){
            if(nums[i] == val){
                for(int j = i+1; j < len; j++){
                // 用目标元素的后一位元素去覆盖目标元素
                    nums[j - 1] = nums[j];
                }
                i--;
                len--;
            }
        }
        return len;
    }
}

时间复杂度:双层for循环,所以为O(n^2)
空间复杂度:O(1)

方法二:快慢指针

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];
            }
        }
        return slow;
    }
}

时间复杂度:O(n)
空间复杂度:O(1)

总结

一:数组为有序数组,同时题目还强调数组中无重复元素,可以考虑使用二分查找法。

二:mid = (left + right) / 2,如果 left 和 right 都很大,加法操作的结果可能会超过整型变量的最大值,从而导致溢出错误。可以使用 mid = left + (right - left) / 2;

三:引用传递。函数返回的是 slow 的值,也就是最终数组中非目标值元素的数量。由于 Java 中的数组是引用类型,因此对数组的修改会对原始数组产生影响,函数不需要显式返回修改后的数组,因为原始数组已经被修改了。这种方式被称为“引用传递”,即传递的是引用(指针),而不是对象本身的拷贝。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值