LeetCode打卡 day02--滑动窗口-长度最小的子数组, 螺旋矩阵小套路


Leetcode 977. 有序数组的平方

题目链接

题目说明

给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序

代码说明

第一个想法便是非常直接的,先算出来平方然后调用Arrary.sort() 方法来以从大到小的顺序排序

class Solution {
    public int[] sortedSquares(int[] nums) {
        for(int i = 0; i < nums.length; i ++){
            nums[i] = nums[i] * nums[i];
        }
        Arrays.sort(nums);
        return nums;
    }
}

但显然这个不是最优解, 时间复杂度为O(N log N)。 Java 源码中对于int array的排序使用快速排序。

更好的方法是运用双指针。因为我们原有的数列是排序的, 平方之后的数字也会呈现出一定的规律–平方最大的数一定会出现在原有数组的两端, 运用双指针就可以直接选出最大平方数。时间复杂度也降到了O(n).

class Solution {
    public int[] sortedSquares(int[] nums) {
        int[] res = new int[nums.length];
        int left = 0, right = nums.length -1;
        for(int i = nums.length -1; i >= 0; i--){
            if(Math.abs(nums[left]) > Math.abs(nums[right])){
                res[i] = nums[left] * nums[left];
                left++;
            }else{
                res[i] = nums[right] * nums[right];
                right--;
            }
        }
        return res;
    }
}

Leetcode 209. 长度最小的子数组

题目链接

题目说明

给定一个含有 n 个正整数的数组和一个正整数 target 。

找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, …, numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。

代码说明

我们要找到最短的连续子数组满足其和大于targer, 使用滑动窗口是一个不错的选择。 但是要注意边界情况。当fast指针到达最右边的时候, 应该继续判断是否可以进一步缩小. 滑动窗口采取左闭右开的情况, windowLen = fast - slow

// 左闭右开
class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int slow = 0, fast = 0;
        int minLen = Integer.MAX_VALUE;
        int curSum = 0;
        while(fast <= nums.length){
            if(curSum >= target){
                minLen = Math.min(minLen, fast - slow);
                curSum = curSum - nums[slow];
                slow++;
            }else{
                if (fast == nums.length){
                    break;
                }
                curSum += nums[fast];
                fast++;
            }
        }
        return minLen == Integer.MAX_VALUE ? 0 : minLen; 
    }
}

如果采取左闭右闭, 则代码需要做稍微的调整。

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int slow = 0, fast = 0;
        int minLen = Integer.MAX_VALUE;
        int curSum = nums[0];
        while(fast < nums.length){
            if(curSum >= target){
                minLen = Math.min(minLen, fast - slow + 1 );
                curSum = curSum - nums[slow];
                slow++;
            }else{
                if (fast == nums.length - 1){
                    break;
                }
                fast++;
                curSum += nums[fast];
            }
        }
        return minLen == Integer.MAX_VALUE ? 0 : minLen; 
    }
}

LeeCode 54. 螺旋矩阵

题目链接

题目说明

给你一个 m 行 n 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。

在这里插入图片描述

代码说明

这种用right, left, top, bottom还有numEle的模版非常好理解, 而且避免了特殊情况的考虑, 也不用判断矩阵是否为正方形. 非常好用!!!

class Solution {
    public List<Integer> spiralOrder(int[][] matrix) {
        List<Integer> res = new ArrayList<>();
        if(matrix == null || matrix.length == 0) return res;
        int left = 0, right = matrix[0].length -1, top = 0, bottom = matrix.length -1;
        int numEle = (right + 1) * (bottom + 1);
        while(numEle > 0){
            for(int i = left; i <= right && numEle > 0; i++){
                res.add(matrix[top][i]);
                numEle--;
            }
            top++;

            for(int i = top; i<= bottom && numEle > 0; i++){
                res.add(matrix[i][right]);
                numEle--;
            }
            right--;

            for(int i = right; i>=left && numEle > 0;i--){
                res.add(matrix[bottom][i]);
                numEle--;
            }
            bottom--;

            for(int i = bottom; i>= top && numEle > 0; i--){
                res.add(matrix[i][left]);
                numEle--;
            }
            left++;
        }
        return res;
   }
}

Leetcode 59. 螺旋矩阵 II

题目链接

题目说明

给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。
在这里插入图片描述

代码说明

这道题看上去很复杂, 实际上算法思想很简单, 就是通过循环一圈又一圈的将数字赋值进去。但是循环的过程中要注意各种边界条件,避免数组越界的行为。每一条边赋值的时候采取左闭右开的方式。

还有一个很有意思的点,就是for循环和whie循环有相似也有不一样的地方

for(int loop = 1; loop < n/ 2 + 1; loop++){}
// 等价于
int loop = 0;
while(loop++ < n/2){}
class Solution {
    public int[][] generateMatrix(int n) {
        int count = 1;
        int[][] res = new int[n][n];
        int start = 0; // 每一圈开始的地方 从[0][0] -> [1][1] -> ... -> [n/2][n/2]
        int i, j;
        for(int loop = 1; loop < n/2 + 1; loop++){
            for(j = start; j < n -loop; j++){
                res[start][j] = count ++;
            }

            for(i = start; i < n - loop; i++){
                res[i][j] = count++;
            }
            for (; j >= loop; j--){
                res[i][j] = count++;
            }
            for(; i >= loop; i--){
                res[i][j] = count++;
            }
            start++;
        }
        if(n % 2 == 1){
            res[start][start] = count;
        }
        return res;
    }
}

在这里我们采取新方法, 代码统一且好理解

class Solution {
    public int[][] generateMatrix(int n) {
        int count = 1;
        int[][] res = new int[n][n];
        int left = 0, right = n-1, top = 0, bottom = n-1;
        int numEle = n * n;

        while(numEle > 0){
            for(int i = left; i<= right && numEle >0; i++){
                res[top][i] = count++;
                numEle--;
            }
            top++;

            for(int i = top; i<= bottom && numEle > 0; i++){
                res[i][right] = count++;
                numEle--;
            }
            right--;

            for(int i = right; i>= left && numEle > 0; i--){
                res[bottom][i] = count++;
                numEle--;
            }
            bottom--;

            for(int i = bottom; i>= top && numEle > 0; i--){
                res[i][left] = count++;
                numEle--;
            }
            left++;
        }
        return res;
    }       
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值