数组【二分,双指针,滑动窗口,模拟】

文章目录

      • 刷题目录
      • 数组的理论知识
      • [35. 搜索插入位置(二分)](https://leetcode-cn.com/problems/search-insert-position/)
      • [27. 移除元素(双指针)](https://leetcode-cn.com/problems/remove-element/)
      • [209. 长度最小的子数组(滑动窗口)](https://leetcode-cn.com/problems/minimum-size-subarray-sum/)
      • [59. 螺旋矩阵 II(模拟)](https://leetcode-cn.com/problems/spiral-matrix-ii/)

刷题目录

数组的理论知识

二维数组不是连续地址空间,而是一个线性数组存放着 其它数组的首地址
数组【二分,双指针,滑动窗口,模拟】_第1张图片

35. 搜索插入位置(二分)

以后大家「只要看到面试题里给出的数组是有序数组,都可以想一想是否可以使用二分法。」
二分出来的一定是符合边界的,但不一定符合题意!要特判!
这一题解法1:二分边界是 >= target的值, 解法2:考虑 二分边界是 <= target的值
时间复杂度:O(logn)

解法1:二分边界是 >= target的值

class Solution {
     
public:
    int searchInsert(vector<int>& nums, int target) {
     
        // 已排好序,二分查找
        int l = 0,r = nums.size() ; // 预留多一个位置,防止插在最后
        while(l < r)
        {
     
            int mid = l + r >> 1;
            if(nums[mid] >= target) r = mid;
            else l = mid + 1;
        }

        return r;
    }
};

解法2:二分边界是 <= target的值

class Solution {
     
public:
    int searchInsert(vector<int>& nums, int target) {
     
        int l = 0, r = nums.size() - 1;
        while(l < r)
        {
     
            int mid = l + r + 1>> 1;
            if(nums[mid] <= target) l = mid;
            else r = mid - 1;
        }

        if(target <= nums[0]) return 0; // 特判
        if(nums[r] != target) return r + 1;
        return r;
    }
};

27. 移除元素(双指针)

双指针,可从O(n ^ 2)降到O(n)
class Solution {
     
public:
    int removeElement(vector<int>& nums, int val) {
     
        // 快慢指针
        // 时间复杂度:O(n)
        // 空间复杂度:O(1)
        int slow = 0;
        for(int fast = 0;fast < nums.size(); fast ++)
        {
     
            if(val != nums[fast]) nums[slow ++ ] = nums[fast];
        }

        return slow;
    }
};

209. 长度最小的子数组(滑动窗口)

滑动窗口:利用单调性优化,可从O(n ^ 2) 降到 O(n)
注意边界:没有符合条件的子数组
class Solution {
     
public:
    int minSubArrayLen(int s, vector<int>& nums) {
     
     	// 时间复杂度O(n)
        int len = nums.size() + 1;
        int sum = 0;
        for(int i = 0, j = 0;i < nums.size();i ++ )
        {
     
            sum += nums[i];
            while(sum >= s)
            {
     
                len = min(len, i - j + 1); // 长度是i - j + 1;
                sum -= nums[j ++ ];
            }
            
        }

        if(len == nums.size() + 1) return 0; // 特判,表示没有符合条件的连续子数组
        return len;
    }
};

59. 螺旋矩阵 II(模拟)

定义四个偏移量,利用方向矢量来模拟
class Solution {
     
public:
    vector<vector<int>> generateMatrix(int n) {
     
        vector<vector<int>> res(n,vector<int>(n)); // 初始化
        vector<vector<bool>> st(n,vector<bool>(n,false)); // 是否访问过

        int dx[4] = {
     -1,0,1,0}, dy[4] = {
     0,1,0,-1}; // 上右下左
        int x = 0,y = 0; // 初始坐标
        int d = 1; // 初始方位
        for(int i = 1;i <= n * n ;i ++ )
        {
     
            res[x][y] = i;
            st[x][y] =  true;
            int tx = x + dx[d], ty = y + dy[d];
            if(tx < 0 || tx >= n || ty < 0 || ty >= n || st[tx][ty]) // 出界或者已访问,就转向
            {
     
                d = (d + 1) % 4;
                tx = x + dx[d], ty = y + dy[d]; // 转向,重新计算坐标
            } 
            x = tx, y = ty;
        }

        return res;
    }
};

你可能感兴趣的:(2021刷题记录,leetcode,算法,数组)