代码随想录算法训练营第二天 | LC977有序数组的平方、LC209长度最小的子数组、、LC59螺旋矩阵Ⅱ

文章讲解:
977.有序数组的平方

977. 有序数组的平方

第一想法

如果用暴力循环,时间复杂度是nlogn.
以0为分界,0左侧逐渐变大,0右侧逐渐变大,新建一个数组,用双指针把平方后的数据放进去

解题思路

同上,不过要注意一下退出循环的条件,自己写的是相等时break,其实可以直接对l ++,然后在此循环发现不满足l <= r.

实现代码

class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
        int n = nums.size();
        int l = 0, r = n - 1;
        vector<int> res(n);
        int m = n - 1;
        for (int i = 0; i < n; i ++)
            nums[i] = nums[i] * nums[i];
        while (l <= r){
            if (l == r){
                res[m] = nums[l];
                break;
            }
            if (nums[l] < nums[r]){
                res[m --] = nums[r--];
            }else{
                res[m --] = nums[l++];
            }
        }
        return res;
    }
};

209. 长度最小的子数组

第一想法

用队列建立一个滑动窗口,遍历整个数组.如果和小于target,一直添加,如果发现添加后大于target,那么需要从队头删除元素,直到小于target,然后再继续添加后面的元素重复上述过程.

存在问题

需要考虑的是,当把队头元素删除后,重新重复上述过程,为什么能够保证新的队列产生符合条件会出现最小.因为题目要求的是连续数组,新添加的数前一位的数已经重复过判断过程,所以一定是向后继续进行规则判断.

解题思路

  1. 实现滑动窗口:队列
  2. 实现滑动窗口:双指针,需要注意长度如何表示

实现代码

  1. 优点笨拙的自我实现
class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        queue<int> res;
        int sum = 0;
        int ans = INT_MAX;
        for (int i = 0; i < nums.size(); i ++){
            if (sum + nums[i] < target){
                res.push(nums[i]);
                sum += nums[i];
            }else{
                res.push(nums[i]);
                sum += nums[i];
                ans = min(ans, int(res.size()));
                while (sum > target){
                    int a = res.front();
                    sum -= a;
                    res.pop();
                    if (sum >= target) ans = min(ans, int(res.size()));
                }
            }
        }
        if (ans == INT_MAX) return 0;
        return ans;
    }
};
  1. 优化了的双指针
class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int l = 0, r = 0;
        int n = nums.size();
        int sum = 0;
        int res = INT_MAX;
        for (; r < n; r ++){
            sum += nums[r];
            while (sum >= target){
                res = min(res, r - l + 1);
                sum -= nums[l++];
            }
        }
        if (res == INT_MAX) return 0;
        return res;
    }
};

59. 螺旋矩阵Ⅱ

第一思路

类似之前做过的顺序打印问题,定义完数组,如何建立规则把数据顺序填充进去.很明确n为偶数和奇数处理方式有区别,需要进行判断.循环规则是按照螺旋,定义为[)的方式,把每一行最后一个留给下一条规则处理.

存在问题

  1. 循环次数n / 2 需要判断奇数
  2. 每次循环都有一个offset

代码实现

class Solution {
public:
    vector<vector<int>> generateMatrix(int n) {
        int m = n / 2;
        int x = 0, y = 0;
        vector<vector<int>> res(n, vector<int> (n, 0));
        int count = 1;
        int t = 1;
        while (m --){
            int i, j;
            for (j = y; j < n - t; j ++) res[x][j] = count ++;
            for (i = x; i < n - t; i ++) res[i][j] = count ++;
            for (; j > y; j --) res[i][j] = count ++;
            for (; i > x; i --) res[i][j] = count ++;
            x ++, y ++, t ++;
        }
        if (n % 2 == 1) res[n / 2][n / 2] = count;
        return res;
    }
};

数组总结

基本理解

  • 数组的是行先序,按照行先分配内存,所以循环要注意i j的分布,提高效率.
  • 二维数组看似是连续的,实际上是通过指针进行地址链接,具体可以看vector实现

方法总结

二分法

留意边界问题,规则是按照[]还是[)决定

双指针法

滑动窗口

注意滑动窗口的规则指定

模拟行为

如何处理边界问题,首先定义好[)

你可能感兴趣的:(算法,矩阵,c++,leetcode,数据结构)