• 随想录一刷Day01——数组


    Day01_数组

    1. 数组理论基础

    地址连续,利用下标访问
    访问时间 O ( 1 ) O(1) O(1)
    删除元素需要将后面的元素依次前移 O ( n ) O(n) O(n)

    2. 二分查找

    704. 二分查找

    思路:

    由于数组有序,每次寻找区间中间的元素,将目标值与其做对比,即可通过大小关系将查询区间折半。

    代码随想录给出了二分查找的两种写法,全闭区间和半开区间
    写法一:
    区间全闭 [ l e f t , r i g h t ] [left, right] [left,right]
    结束条件为 l e f t > r i g h t left > right left>right ,因为 l e f t = = r i g h t left == right left==right 时取值有意义
    区间折半时,要把中间值去掉,因为已经访问过了

    class Solution {
    public:
        int search(vector<int>& nums, int target) {
            int nums_size = nums.size();
            int left = 0, right = nums_size - 1; // 右闭
            while (left <= right) {
                int mid = left + ((right - left) >> 1); // 防止溢出
                if (nums[mid] == target) return mid;
                else if (nums[mid] > target) right = mid - 1; // 找到的数字大了,在较小数字区间(左半区间)找
                else left = mid + 1; // 找到的数字小了,去右半区间找
            }
            return -1;
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    写法二:
    区间左闭右开 [ l e f t , r i g h t ) [left, right) [left,right
    结束条件为 l e f t > = r i g h t left >= right left>=right ,因为 l e f t = = r i g h t left == right left==right 时取值已经超出了数据范围
    区间折半时,要把右边界置为中间值,因为已经右边界为开区间,不会造成重复访问

    class Solution {
    public:
        int search(vector<int>& nums, int target) {
            int nums_size = nums.size();
            int left = 0, right = nums_size; // 右开
            while (left < right) {
                int mid = left + ((right - left) >> 1);
                if (nums[mid] == target) return mid;
                else if (nums[mid] < target) left = mid + 1;
                else right = mid; // 右开
            }
            return -1;
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    3. 移除元素(双指针

    27. 移除元素
    简单的小题,美妙的思想,双指针来啦!
    思路:

    思路一:
    暴力解,删除一个元素将其后所有元素依次前移,最坏情况需要调整 n n n 次,时间复杂度 O ( n 2 ) O(n^2) O(n2)

    思路二:
    双指针,设置两个指针向前遍历数组,一个快指针向前遍历数组,[0, 慢指针]存放的是[0, 快指针]中删除val之后剩余的元素。
    遍历过程:

    1. 快指针向前移动一下,如果nums[fast_index] == val,需要删除该元素,则慢指针不需要动,因为需要保留的元素个数不需要扩充。
    2. 快指针向前移动一下,如果nums[fast_index] != val,需要保留该元素,则慢指针向前移动一位,扩充数组空间来存放nums[fast_index]
    class Solution {
    public:
        int removeElement(vector<int>& nums, int val) {
            int nums_size = nums.size();
            int fast_index = 0, slow_index = 0;
            for (fast_index = 0; fast_index < nums_size; ++fast_index) {
                if (nums[fast_index] != val) { // 扩充答案数组,保留该元素
                    nums[slow_index] = nums[fast_index];
                    slow_index++; // 保留新元素后,慢指针要移动到下一个空的位置,方便下次保存元素
                }
            }
            return slow_index; // [0, slow_index)是最终的答案数组
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    由于slow_index++是先运算,再自增1,所以可以将上面扩充新数组的代码部分简化

    class Solution {
    public:
        int removeElement(vector<int>& nums, int val) {
            int nums_size = nums.size();
            int fast_index = 0, slow_index = 0;
            for (fast_index = 0; fast_index < nums_size; ++fast_index) {
                if (nums[fast_index] != val) { // 扩充答案数组,保留该元素
                    nums[slow_index++] = nums[fast_index];
                }
            }
            return slow_index; // [0, slow_index)是最终的答案数组
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
  • 相关阅读:
    表单识别(三)
    关于用pygame来编写类满天星游戏的全记录
    C#的托盘窗体显示与隐藏效果 - 开源研究系列文章
    LeetCode 26. 删除有序数组中的重复项
    springmvc入门
    插值与拟合的区别以及如何选取
    Vue项目前端代码防止被调试
    maven-安装maven
    SSH智能社区住户信息管理系统
    基于BS的在线考试系统设计与开发
  • 原文地址:https://blog.csdn.net/zhiai_/article/details/126976899