代码随想录刷题Day2 | 977.有序数组的平方 ,209.长度最小的子数组 ,59.螺旋矩阵II

代码随想录刷题Day2 | 977.有序数组的平方 ,209.长度最小的子数组 ,59.螺旋矩阵II

977.有序数组的平方

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

思路:

  1. 暴力解法:对数组中的每个数字平方,然后重新排序,时间复杂度为较高(不同的排序算法有不同的时间复杂度)
  2. 双指针解法:左指针指向最左边元素,右指针指向最右边元素,比较绝对值的大小,首先计算绝对值最大的元素的平方,然后向中间移动该指针,循环该步骤,得到非递减顺序的每个数字的平方的排序,然后反转该数组。

代码:

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

时间复杂度:O(n),空间复杂度:O(n)

209.长度最小的子数组

题目: 给定一个含有n个正整数的数组和一个正整数 target 。找出该数组中满足其和 ≥ target长度最小的 连续子数组[numsl, numsl+1, ..., numsr-1, numsr],并返回其长度。如果不存在符合条件的子数组,返回 0 。

思路: 采用划定窗口的形式,也就是双指针,一个指针指向窗口的头部,定义为right,一个指针指向窗口的尾部,为left,初始时,两个指针均指向index为0的位置,right指针开始遍历nums数组,当left到right之间的值的和大于target时,left开始移动到和小于target,然后继续移动right直至最后。(如果遇到nums[right]>target直接返回1)

代码:

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int left = 0, right = 0, result = Integer.MAX_VALUE, sum = 0;
        while(right <= nums.length - 1){
            if(nums[right] >= target) return 1;
            sum += nums[right];
            while(sum >= target){
                sum -= nums[left++];
                result = right - left + 2 < result ? right - left + 2 : result;
            }
            right++;
        }
        return result > nums.length ? 0 : result;
    }
}

时间复杂度:O(n),空间复杂度O(1)

59.螺旋矩阵II

题目: 给你一个正整数 n ,生成一个包含 1n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix

示例:

img

输入:n = 3
输出:[[1,2,3],[8,9,4],[7,6,5]]

思路: 模拟该算法,定义dir变量代表四个方向,到边界时换到下一个方向。边界判断方法为:1. 到达边界,比如上图中的3 2.下一个位置已经遍历过,比如说上图中的8

代码:

class Solution {
    public int[][] generateMatrix(int n) {
        int[][] result = new int[n][n];
        int dir = 0;//定义方向变量,0,1,2,3代表不同的方向,每次改变方向,dir + 1
        int i = 0, j = 0;
        for(int num = 1; num <= n* n; num++){
            if(dir % 4 == 0){
                result[i][j] = num;
                if(j == n - 1 || result[i][j+1] != 0){
                    i++;
                    dir++;
                    continue;
                }
                j++;
            }else if(dir % 4 == 1){
                result[i][j] = num;
                if(i == n - 1 || result[i+1][j] != 0){
                    j--;
                    dir++;
                    continue;
                }
                i++;
            }else if(dir % 4 == 2){
                result[i][j] = num;
                if(j == 0 || result[i][j-1] != 0){
                    i--;
                    dir++;
                    continue;
                }
                j--;
            }else if(dir % 4 == 3){
                result[i][j] = num;
                if(result[i-1][j] != 0){
                    j++;
                    dir++;
                    continue;
                }
                i--;
            }
        }
        return result;
    }
}

时间复杂度为O(nxn),空间复杂度为O(nxn)

总结

  1. 对于有序不重复数组,使用二分查找更加简单快捷,使用二分查找时,注意边界情况。
  2. 数组不能删除,只能覆盖。
  3. 双指针可以使一些数组的操作变得简单,遇到数组相关的问题,可以先想一下是否可以使用双指针,一般使用双指针的形式有快慢指针,和指向两端的双指针。
  4. 滑动窗口也是一种特殊的双指针形式,要注意什么时间移动哪一个指针。

查找时,注意边界情况。
2. 数组不能删除,只能覆盖。
3. 双指针可以使一些数组的操作变得简单,遇到数组相关的问题,可以先想一下是否可以使用双指针,一般使用双指针的形式有快慢指针,和指向两端的双指针。
4. 滑动窗口也是一种特殊的双指针形式,要注意什么时间移动哪一个指针。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值