代码随想录算法训练营第二天_第一章_数组 | 977.有序数组的平方、209.长度最小的子数组、59.螺旋矩阵Ⅱ

LeetCode 977.有序数组的平方

题目描述:非递减数组nums,将各元素平方按非递减顺序排列,返回新数组

  • 双指针:left从左往右,right从右往左,比较平方数,对新数组从大到小(从右往左)赋值

视频讲解https://www.bilibili.com/video/BV1QB4y1D7ep/?vd_source=f98f2942b3c4cafea8907a325fc56a48

文章讲解https://programmercarl.com/0977.%E6%9C%89%E5%BA%8F%E6%95%B0%E7%BB%84%E7%9A%84%E5%B9%B3%E6%96%B9.html

笔记整理:

  • 思路:
    • nums元素组成可能为:①全正;②全负;③有正有负;
    • 对于有正有负的情况,需要比较负数平方与正数平方,才能决定在新数组中的位置
    • 用一个指针扫描负数,一个指针扫描正数,①②可合并到③(一个指针始终未更新)
  • 代码:
class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
        vector<int> ans(nums.size(), 0);
        int left = 0;
        int right = nums.size() - 1;
        for (int i = nums.size() - 1; i >= 0; i--) {
            if (nums[left] * nums[left] > nums[right] * nums[right]) {
                ans[i] = nums[left] * nums[left];
                left++;
            }
            else {
                ans[i] = nums[right] * nums[right];
                right--;
            }
        }
        return ans;
    }
};

LeetCode 209.长度最小的子数组

题目描述:给定正整数数组nums和正整数target,找和>=target长度最小连续子数组;找到返回其长度,找不到返回0;

  • 滑动窗口:[left, right],一层for:对于每一个固定的右界,找符合条件的左界,更新最小长度

视频讲解https://www.bilibili.com/video/BV1tZ4y1q7XE/文章讲解https://programmercarl.com/0209.%E9%95%BF%E5%BA%A6%E6%9C%80%E5%B0%8F%E7%9A%84%E5%AD%90%E6%95%B0%E7%BB%84.html#%E5%85%B6%E4%BB%96%E8%AF%AD%E8%A8%80%E7%89%88%E6%9C%AC笔记整理:

  • 思路:
    • 暴力解法:两层for
      • 外层为起始位置,每轮重置sum = 0;
      • 内层为终止位置,从起始位置开始向后遍历,一旦sum >= target就break;
      • 对于每个起止位置,找符合条件的最小长度子数组,判断更新result
      • 每一轮固定起始位置,而终止位置会走回头路,考虑进行优化
    • 滑动窗口:
      • 每一轮固定终止位置
      • 当sum >= target时,不断右移起始位置来缩小窗口,判断更新result
      • 子数组[left, right]长度为:right - left + 1

  • 代码:
class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int left = 0;
        // 当前子数组元素和
        int sum = 0;
        // 符合条件的子数组长度
        int subLength = 0;
        // 最小长度
        int result = INT32_MAX;
        // 移动右界
        for (int right = 0; right < nums.size(); right++) {
            sum += nums[right];
            while (sum >= target) {
                // 计算子数组长度
                subLength = right - left + 1;
                // 更新最小长度
                result = result > subLength ? subLength : result;
                // 移动左界
                sum -= nums[left++];
            }
        }
        return result == INT32_MAX ? 0 : result;
    }
};

LeetCode 59.螺旋矩阵Ⅱ

题目描述:给定正整数n,将1到n²按顺时针顺序填入n×n的正方形矩阵,返回该矩阵。

  • 循环不变量:考虑每一圈的四条边按左闭右开进行处理

视频讲解https://www.bilibili.com/video/BV1SL4y1N7mV/文章讲解https://programmercarl.com/0059.%E8%9E%BA%E6%97%8B%E7%9F%A9%E9%98%B5II.html

笔记整理:

  • 思路:
    • 每一圈从(startx, starty)位置开始
      • 上:行号不变,列号从 starty(闭)到 starty + n - offset(开)
      • 右:行号从 startx(闭)到 startx + n - offset(开),列号不变
      • 下:行号不变,列号从 starty + n - offset(闭)到 starty(开)
      • 左:行号从 startx + n - offset(闭)到  startx(开)
      • 更新startx、starty、offset(每次+2)
    • n为奇数,单独处理中心位置

  • 代码:
class Solution {
public:
    vector<vector<int>> generateMatrix(int n) {
        vector<vector<int>> res(n, vector<int>(n, 0));
        // 每一圈的起始位置
        int startx = 0;
        int starty = 0;
        // 需处理的圈数
        int loop = n / 2;
        int mid = n / 2;
        // 填入值
        int count = 1;
        // 用于确定每一圈的边长
        int offset = 1;
        int i, j;
        while (loop--) {
            // 上
            for (j = starty; j < starty + n - offset; j++) {
                res[startx][j] = count++;
            }
            // 右
            for (i = startx; i < startx + n - offset; i++) {
                res[i][j] = count++;
            }
            // 下
            for (; j > starty; j--) {
                res[i][j] = count++;
            }
            // 左
            for (; i > startx; i--) {
                res[i][j] = count++;
            }
            startx++;
            starty++;
            offset += 2;
        }
        // 对奇数单独处理
        if (n % 2) {
            res[mid][mid] = count;
        }
        return res;
    }
};

数组总结

(待补充)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值