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

96 阅读3分钟

977.有序数组的平方

题目链接:977.有序数组的平方

解题思路

1、暴力解法。按照题目意思,先平方后排序。
2、双指针解法。已知原数组为有序数组,所以平方后 新数组的最大值一定在原数组的最左或最右。即只需将原数组左右的数的平方进行比较,把大的数放在新数组的右边进行数组的排序。

代码

暴力解法:
var sortedSquares = function(nums){
	let len = nums.length;
	let i = 0;
	for (; i < len; i++) { nums[i] *= nums[i]; }
	nums.sort((a,b) => a - b);
	return nums;
};
双指针解法:
var sortedSquares = function(nums) {
    let n = nums.length;
    let arr = new Array(n).fill(0);
    let i = 0, j = n - 1, k = n - 1;
    while(i <= j) {
        let left = nums[i] * nums[i],
            right = nums[j] * nums[j];
        if(left < right) {
            arr[k--] = right
            j--
        } else {
            arr[k--] = left
            i++
        }
    }
    return arr
};

总结

双指针方法在解题时很好用,重点是要理解题目中的隐藏条件,多变换思路。
同一值被重复使用时,注意先将该值定义赋值,使代码更加清晰好理解。


209.长度最小的子数组

题目链接:209.长度最小的子数组

解题思路

1、暴力解法。两个for循环,然后不断的寻找符合条件的子序列,时间复杂度很明显是O(n^2)。(已经无法在leetcode上运行,超时)
2、滑动窗口解法。不断的调节子序列的起始位置和终止位置,确定窗口是否满足所给条件,取子序列的长度的最小值。

在本题中实现滑动窗口,主要确定如下三点:

  • 窗口内是什么?
  • 如何移动窗口的起始位置?
  • 如何移动窗口的结束位置?

窗口就是 满足其和 ≥ s 的长度最小的 连续 子数组。
窗口的起始位置如何移动:如果当前窗口的值大于s了,窗口就要向前移动了(也就是该缩小了)。
窗口的结束位置如何移动:窗口的结束位置就是遍历数组的指针,也就是for循环里的索引。

代码

滑动窗口
var minSubArrayLen = function(target, nums) {
    let start, end
    start = end = 0
    let sum = 0
    let len = nums.length
    let ans = Infinity

    while(end < len){
        sum += nums[end];
        while (sum >= target) {
            ans = Math.min(ans, end - start + 1);
            sum -= nums[start];
            start++;
        }
        end++;
    }
    return ans === Infinity ? 0 : ans
};

相关题目推荐

总结

理解题目含义,注意断句。滑动窗口与双指针法的一丝丝区别在于:滑动窗口是两指针所在范围内的元素,双指针只关注指针所在位置的元素。


59.螺旋矩阵II

题目链接:59.螺旋矩阵II

解题思路:

1、坚持一个原则来处理每条边。左闭右开。
2、分情况考虑问题,n为单数或复数。

代码:

var generateMatrix = function(n) {
    let startX = startY = 0;
    let loop = Math.floor(n/2);
    let mid = Math.floor(n/2);
    let offset = 1;
    let count = 1;
    let res = new Array(n).fill(0).map(() => new Array(n).fill(0));

    while(loop--){
        let row = startX, col = startY;
        
        for (; col < startY + n - offset; col++) {
            res[row][col] = count++;
        }
        for (; row < startX + n - offset; row++) {
            res[row][col] = count++;
        }
        for (; col > startY; col--) {
            res[row][col] = count++;
        }
        for (; row > startX; row--) {
            res[row][col] = count++;
        }

        startX++;
        startY++;

        offset += 2;
    }

    if (n % 2 === 1) {
        res[mid][mid] = count;
    }
    return res;
};

类似题目

  • 54.螺旋矩阵
  • 剑指Offer 29.顺时针打印矩阵

总结

切记:清楚每一步对应的变量与不变量,以及n为单数或复数两种情况。

今日小结

训练营的第二天!
有序数组的平方运用了双指针方法,数组的左右两端为起始位置。
长度最小的子数组运用了双指针的另一种形式,把两指针及其中间部分看作窗口,进行解题。
螺旋矩阵应注意考虑问题要全面。
第三天也要加油鸭!