Day1 数组:704.二分查找 27.移除元素

数组理论基础

⚠️C++er 要注意:

vector 和 array 的区别,vector的底层实现是array,严格来讲vector是容器,不是数组。

Day1. 数组:704.二分查找

题目链接:https://leetcode.cn/problems/binary-search/

文章讲解:https://programmercarl.com/0704.二分查找.html

视频讲解:https://www.bilibili.com/video/BV1fA4y1o715

使用二分法的前提条件:

  • 数组是有序数组
  • 数组中无重复元素

二分法的2种常见写法:左闭右闭、左闭右开

“二分查找涉及的很多的边界条件,逻辑比较简单,但(很多同学)就是写不好。

例如到底是 while(left < right) 还是 while(left <= right)

到底是right = middle呢,还是要right = middle - 1呢?”

对区间的不一样的定义,会影响到我们在写二分法时这个边界条件的处理。

左闭右闭写法:

[left, right]

eg: [1, 1]

边界的处理规则都是根据对这个区间的定义来写的。

定义target是在上面这个左闭右闭的区间里,当target出现在middle的左边,我们需要思考接下来是middle 还是middle - 1

回到这个区间的定义,这是一个左闭右闭的区间,我们已经判断middle所在的值已经大于target了,说明nums[middle]一定不是我们要搜索的值。

那么接下来的区间就一定不会包含这个数值,
既然不包含,就应该是在[left, middle - 1] 这个区间进行搜索。

AC代码: (核心代码模式)

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int left = 0;
        int right = nums.size() - 1;
        
        while (left <= right) {
            int middle = left + ((right - left) / 2);  //防止溢出的写法,相当于:(left + right) / 2
            if (nums[middle] > target) {  //目标值在middle左边
                right = middle - 1;  //更新右区间
            }
            else if (nums[middle] < target) {  //目标值在middle右边
                left = middle + 1;  //更新左区间
            }
            else
                return middle;
        }

        return -1;
    }
};

左闭右开写法:

[left, right)

eg:[1, 1) 即包含1,又不包含1。这是一个不合法的区间。

left和right相等的情况在这个区间里没有意义,因此考虑while (left < right)

nums[middle]已经大于target了,说明下一个搜索的左区间是不包含这个middle所在的数值的,

那么这个right直接等于middle就可以了。

⚠️注意:right = nums.size();
因为我们这个区间里面不包含右边界了。

AC代码: (核心代码模式)

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int left = 0;
        int right = nums.size();
        
        while (left < right) {
            int middle = left + ((right - left) / 2);
            if (nums[middle] > target) {
                right = middle;
            }
            else if (nums[middle] < target) {
                left = middle + 1;
            }
            else
                return middle;
        }

        return -1;
    }
};


Day1. 数组:27.移除元素

题目链接:https://leetcode.cn/problems/remove-element/

文章讲解:https://programmercarl.com/0027.移除元素.html

视频讲解:<htt ps://www.bilibili.com/video/BV12A4y1Z7LP>

暴力解法:

时间复杂度:O(n^2)

空间复杂度:O(1)

写2层for循环:1️⃣第一层循环遍历数组元素。 2️⃣第二层循环更新数组

AC代码: (核心代码模式)

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int size = nums.size();
        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以后的数值都向前移动了一位,所以i也向前移动一位
                size--; // 此时数组的大小-1
            }
        }
        return size;

    }
};

双指针解法:(重点)

时间复杂度:O(n)

空间复杂度:O(1)

快指针是获取新数组中的元素,慢指针是获取新数组中需要更新的位置,都是在同一个数组上进行操作。

在这里插入图片描述

AC代码: (核心代码模式)

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int slowIndex = 0;
        for (int fastIndex = 0; fastIndex < nums.size(); fastIndex++) {
            if (val != nums[fastIndex]) {
                nums[slowIndex] = nums[fastIndex];
                slowIndex++;
            }
        }
        return slowIndex;
    }
};
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值