代码随想录算法打卡 Day1-数组理论基础 + 二分查找 + 移除元素

数组理论基础

安利数组理论基础文章:https://programmercarl.com/%E6%95%B0%E7%BB%84%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html

关键要点:

  • 数组下标都是从 0 开始的
  • 数组内存空间的地址是连续的
  • 数组的元素是不能删的,只能覆盖

Leetcode 704-二分查找

相似题目:

35.搜索插入位置
34. 在排序数组中查找元素的第一个和最后一个位置

题目描述:

https://leetcode.cn/problems/binary-search/

在这里插入图片描述

解题思路

二分查找法虽然逻辑简单,思路清晰,但很容易在循环条件、+1-1 这种小细节上出现问题。在这道题中,while 循环条件里 left<right 还是 left<=right 会直接影响到后面的处理。具体情况如下:

左闭右闭

  • 当区间为左闭右闭时,即 left<=right,代码如下:
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) / 2;
            //也可以写成int middle = left + (right - left) / 2,这样的好处是可以防止溢出
            if (target < nums[middle]) { 
                right = middle - 1;//前面已经判断target<middle,因此在下一次循环中不需要将middle纳入考虑中
            }
            else if (target > nums[middle]) {
                left = middle + 1;//同前,无需在下一次循环中考虑middle
            }
            else {
                return middle;
            }
        }
        // 如果在数组中没有找到target值
        return -1;
    }
};

左闭右开

当区间为左闭右开,即 left < right,代码如下:

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int left = 0;
        int right = nums.size();//右为开区间
        while (left < right) {//左闭右开
            int middle = (left + right) / 2;
            //也可以写成int middle = left + (right - left) / 2,这样的好处是可以防止溢出
            if (target < nums[middle]) {
                right = middle;//右面是开区间,区间中本身不包含nums[middle]
            }
            else if (target > nums[middle]) {
                left = middle + 1;//左闭,考虑middle+1
            }
            else {
                return middle;
            }
        }
        // 如果在数组中没有找到target值
        return -1;
    }
};

Leetcode 27-移除元素

题目描述:

https://leetcode.cn/problems/remove-element/

在这里插入图片描述

解题思路:

暴力解法

这道题上来最简单的思路是直接暴力求解,即遍历数组中的每一个元素,如果这个元素的值与目标值相同,则让该元素后面的元素全部向前移动一位,但注意其时间复杂度为 O(n^2),并不是本道题的最优解

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int count = nums.size();
        for (int i = 0; i < count; i++) {
            if (nums[i] == val) {
                for (int j = i + 1; j < count; j++) {
                    nums[j -1] = nums [j]; //每找到一个目标值,后面的元素向前覆盖1
                }
                i--;
                count--;
            }    
        }
        return count;
    }
};

双指针解法

移除元素这道题目可以通过双指针的引入简化时间复杂度,双指针的思路为设置一个快指针和一个慢指针,快指针的作用是判断 nums 中的元素是否等于目标值,而慢指针的作用是确定新数组中存放元素的 index

在这里插入图片描述

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int slow = 0;
        for (int fast = 0; fast < nums.size(); fast++) {
            if (nums[fast] != val) {
                nums[slow] = nums[fast];//如果fast指针搜索到的元素不是目标值,则将该元素放入新的数组中
                slow++;//有新的元素放入新数组中则slow指针+1
            }
        }
        return slow;
    }
};
  • 6
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值