首页 > 编程语言 >代码随想录算法训练营第一天|704.二分查找、27.移除元素

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

时间:2023-01-11 22:45:56浏览次数:70  
标签:27 target nums int 随想录 middle right 移除 left

一、参考资料

数组理论基础

文章链接:https://programmercarl.com/%E6%95%B0%E7%BB%84%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html

二分查找

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

文章讲解:https://programmercarl.com/0704.%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE.html

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

移除元素

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

文章讲解:https://programmercarl.com/0027.%E7%A7%BB%E9%99%A4%E5%85%83%E7%B4%A0.html

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

二、LeetCode704-二分查找

我的代码
class Solution {
public:
    int search(vector<int>& nums, int target) {
        int left = 0, right = nums.size() - 1;
        cout << left << ' ' << right<<endl; 
        while(left <= right){
            int mid = (left + right) / 2;
            if(nums[mid] == target){
                return mid;
            }
            else if(nums[mid] > target){
                right = mid - 1;
            }
            else{
                left = mid + 1;
            }
        }
        return -1;
    }
};

遇到的问题:

  1. 好久没刷题,基本语法还要再熟悉的,size和length需要区分一下
  2. left注意初始化的问题,不然会编译报错
  3. mid如果为了防止溢出,可采用left + (right - left) / 2
  4. 今天写之前花了点时间看代码规范的问题!还是很有必要的,学习到很多细节问题,以后也要慢慢注重培养呢
  5. 对于二分查找的方法,理解起来觉得并不难,但是看完视频讲解和文章,才认识到有“左闭右闭”及“左闭右开”两种思路,这直接影响到代码的逻辑实现

 

接下来学习一下规范的代码实现:

左闭右闭
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;
    }
};
左闭右开
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;
    }
};

三、LeetCode27-移除元素

这题有两种解法,分别是暴力求解和双指针

思路一:暴力求解-第一层for循环枚举所有数组的元素,第二层for循环做元素的覆盖,当找到与目标值相同的元素时,在第二层循环中依次将后续元素向前移动。

暴力求解-代码实现
// 时间复杂度:O(n^2)
// 空间复杂度:O(1)
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)
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];
            }
        }
        return slowIndex;
    }
};

 

标签:27,target,nums,int,随想录,middle,right,移除,left
From: https://www.cnblogs.com/ucaszym/p/17045096.html

相关文章