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

704. 二分查找

首先明确题目给出的是有序且无重复元素的数组,这是使用二分法的前提。

题目唯一的难点就在于划分区间时边界条件的处理,遇到处理区间问题时此前一直的做法就是先把边界写好,至于边界点是否考虑在内再去带入数据验证,或者记住一套固定模板,没什么效率和固定的思路可言。

题解中提供了很好的结题思路,划分区间时停止循环的条件分两种情况来考虑。

  • 第一种考虑方式,target是在一个闭区间[left, right]里,此时left == right是有意义的(存在左右边界相等的情况),循环条件设定为left <= right,这种情况下if (target < nums[mid])时,right赋值为mid - 1(已经判断过这一轮循环里nums[middle] != target) 。

相应代码如下:

class Solution {
    public int search(int[] nums, int target) {
        int left = 0, right = nums.length - 1;
        //假定区间为[left, right]
        while (left <= right) {
        //[left, right], left == right为合法情况
            int mid = left + (right - left) /2;
            //为防止两个int型变量相加溢出,本质上等价于(left + right) / 2
            if (target < nums[mid]) right = mid - 1;
            //target在左区间中 --> [left, mid - 1]
            else if (target > nums[mid]) left = mid + 1;
            //target在右区间中 -->[mid + 1, right]
            else return mid;
            //找到目标值,返回索引
        }
        return -1;
        //未找到目标值
    }
}
  • 第二种考虑方式,target是在一个左闭右开区间[left, right)里,此时left = right没有意义(左端点一定小于右端点),循环条件设定为left < right,这种情况下if (target < nums[mid])时,right赋值为mid(已经判断过这一轮循环里nums[middle] != target,但是寻找区间是左闭右开,所以right更新为mid,而在下一轮寻找时不会再比较mid对应的位置) 。

相应代码如下:

class Solution {
    public int search(int[] nums, int target) {
        int left = 0, right = nums.length;
        //注意,right初值要设定为 数组最大索引+1,否则会漏掉右边界元素
        while (left < right) {
        //如果 left == right, 区间[left, right)无效,所以不能取等
            int mid = left + (right - left) /2;
            if (target < nums[mid]) right = mid;
            //target在区间[left, mid)中
            else if (target > nums[mid]) left = mid + 1;
            else return mid;
        }
        return -1;
    }
}

参考文章链接:
代码随想录_704.二分查找

27. 移除元素

数组原地进行元素删除,不能简单的把元素删除理解为单独删掉某个元素,因为数组的在内存中连续存储的特性,每删除一个中间元素,需要把后续的元素往前移;后续元素覆盖中间元素并整体前移的操作即为删除某一中间元素。

那么在遍历数组时,如果与目标值val不相等,如何确定该元素移动位置呢?

  • 如果考虑暴力求解,思路则非常简单,每删除一个元素那么后续所有元素整体向前移动一位。带来的问题就是时间复杂度较高为 O ( n 2 ) O(n^2) O(n2)
  • 面对这种情况,一般考虑使用快慢双指针实现。快指针fastIndex用来对原数组整体遍历,并进行判断是否和目标值val相等,而慢指针sloowIndex则负责实现保留新数组元素。
    • 如果fastIndex指向的元素不等于val,则该元素一定是新数组中的一个元素,把它复制到lastIndex指向的位置,且两个指针都要右移
    • 如果fastIndex指向的元素等于val,则该元素需要删除,左指针slowIndex不动,右指针fastIndex右移一位(该元素会在后续slowIndex指向时,被新复制的元素覆盖,或新数组的下标到不了该位置,故右指针直接后移,无需处理)

相应代码如下:

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

参考文章链接:
代码随想录_27.移除元素

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值