代码随想录训练营day1 | 704. 二分查找、27. 移除元素。

704原文:代码随想录 (programmercarl.com)

27原文:代码随想录 (programmercarl.com)

二分查找

题目简述

一个有序数组中找到目标值,返回其位置

思路

先设定初始区间,左和右。

  1. 闭区间

先找中间值,如果中间值大于目标值,目标值在左边,中间值也比过了,right变成middle-1。如果中间值小于目标值,目标值在右边,中间值也比了,left变成middle+1。

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int left = 0;
        int right = nums.size() - 1; // 定义target在左闭右闭的区间里,[left, right]
        while (left <= right) { // 当left==right,区间[left, right]依然有效,所以用 <=
            int middle = left + ((right - left) / 2);// 防止溢出 等同于(left + right)/2
            if (nums[middle] > target) {
                right = middle - 1; // target 在左区间,所以[left, middle - 1]
            } else if (nums[middle] < target) {
                left = middle + 1; // target 在右区间,所以[middle + 1, right]
            } else { // nums[middle] == target
                return middle; // 数组中找到目标值,直接返回下标
            }
        }
        // 未找到目标值
        return -1;
    }
};
  1. 左闭右开

先找中间值,如果中间值大于目标值,目标值在左边,中间值没比过,right变成middle。如果中间值小于目标值,目标值在右边,中间值比了,left变成middle+1。

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int left = 0;
        int right = nums.size(); // 定义target在左闭右开的区间里,即:[left, right)
        while (left < right) { // 因为left == right的时候,在[left, right)是无效的空间,所以使用 <
            int middle = left + ((right - left) >> 1);
            if (nums[middle] > target) {
                right = middle; // target 在左区间,在[left, middle)中
            } else if (nums[middle] < target) {
                left = middle + 1; // target 在右区间,在[middle + 1, right)中
            } else { // nums[middle] == target
                return middle; // 数组中找到目标值,直接返回下标
            }
        }
        // 未找到目标值
        return -1;
    }
};

遇到的困难

  1. 找中间值时,避免超出范围,不建议写左加右除以二,建议使用左边值加区间一半写法。因为int有范围,两个大数相加可能超过范围就变成负数了,第二种也存在这种情况,但是发生概率会小点。

  1. 跳出while循环后,就是没找到,返回-1。

移除元素

题目简述

删掉(准确说是覆盖)数组中指定的元素,其他元素可以保留,只要求前面的对就行,后面元素可以不用管。

思路

方法一:暴力求解

两层循环,第一层遍历数组中的每个元素,检查是不是和目标数值一致,第二层循环把后面的元素挨个往前移动,直到外循环没有一样的数就结束。

方法二:双指针法

上面的时间复杂度较大,我们可以加大空间复杂度以减小时间复杂度。

选用两个指针。快指针作用是遍历每一个元素,看看是否有和目标一样的数。慢指针作用是记录删除数据后的位置,保证之前的数据都是对的。

当快指针指向一个数,判断它是否和目标数一样。最开始时,两个一起走,若不一样,快指针前进下一格,慢指针也向下走一步,当遇到一样的时候,快指针向下走,慢指针停下来不动。他俩就错开走了。当遇到不一样的时候,慢指针的值变成快指针的值。若一样,慢指针不懂,快指针走下一格。

最后当快指针遍历完,慢指针指向的位置就是新数组的下一个位置,也就是新数组长度,即可返回。

遇到的困难

  1. 数组不能删除,只能覆盖。

  1. num[slow++]:可以简写是因为slow++先对slow进行运算,算完后再对slow+1。

  1. c++的for循环是分号,不是逗号。每句结尾都要加分号。

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

感受

还是python代码更简洁。

看都第一眼思路就是for循环暴力求解,哈哈。

时间上花费较多,以后尽量写快点。

今日时长3h

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值