数组part02| 977.有序数组的平方、209.长度最小的子数组、59.螺旋矩阵II

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

提示:以下是本篇文章正文内容,下面案例可供参考

977.有序数组的平方(碰撞指针)

1.思路

  • 定义两个指针分别指向原数组的首尾部分,定义一个新数组接收数据
  • 两个指针指向的数据平方后大小比较,值较大的指针将它的数值赋给新数组,并且移动到下一项
  • 两个指针相向而行,直到相遇

2.题解

class Solution {
    public int[] sortedSquares(int[] nums) {
        int right = nums.length - 1;
        int left = 0;
        int[] result = new int[nums.length];
        int index = result.length - 1;
        while (left <= right) {
            if (nums[left] * nums[left] > nums[right] * nums[right]) {
                // 正数的相对位置是不变的, 需要调整的是负数平方后的相对位置
                result[index--] = nums[left] * nums[left];
                ++left;
            } else {
                result[index--] = nums[right] * nums[right];
                --right;
            }
        }
        return result;
    }
}

209.长度最小的子数组(滑动窗口)

1.思路

  • 定义左右两个指针构造一个滑动窗口,开始时都指向数组首元素,定义一个新的元素result来接收结果
  • 右指针不断右移,在这个过程中以左右指针为起始和结尾的所有元素不断求和,当和大于目标元素时右指针停止移动,将此时的左右指针间元素个数赋给result
  • 左指针开始向右移动,每次都比较窗口元素和是否大于目标元素,若大于,就将此时左右指针间元素个数和result比较,把较小值新赋给result
  • 当这个窗口中元素的值不满足和大于目标元素时左指针停止移动
  • 右指针重新移动,重复进行前面三步,直到右指针走到数组最后,左指针也无法移动

2.题解

class Solution {

    // 滑动窗口
    public int minSubArrayLen(int s, int[] nums) {
        int left = 0;
        int sum = 0;
        //result初始值赋值最大值,保证能将滑动窗口第一次满足条件时的值赋给result
        int result = Integer.MAX_VALUE;
        for (int right = 0; right < nums.length; right++) {
            sum += nums[right];
            while (sum >= s) {
                result = Math.min(result, right - left + 1);
                sum -= nums[left++];
            }
        }
        return result == Integer.MAX_VALUE ? 0 : result;
    }
}
注意result初始值的设置

59.螺旋矩阵II

1.思路

  • 首先确定要转的圈数为n/2,并且奇数数情况要考虑正方形矩阵最中间元素为nums[n/2][n/2]
  • 定义填充数字count,不断自增填入数组
  • 定义横向、纵向起始值每次开始新循环都加1,定义offset = 1需要控制每一条边遍历的长度,每次循环offset+1,右边界收缩一位
  • 判断边界后,开始用count给数组元素赋值,分别考虑四种情况:上侧从左到右,右侧从上到下,下侧从右到左,左侧从下到上(全程保持左闭右开,不给最后一个元素赋值)
  • 循环n/2次,把正方形矩阵填充,若存在阵最中间元素再单独赋一次值

2.题解

class Solution {
    public int[][] generateMatrix(int n) {
        int startx=0;
        int starty=0;
        int loop = n/2;  // 控制循环次数
        int mid = n/2; // 矩阵中间的位置,例如:n为3, 中间的位置就是(1,1),n为5,中间位置为(2, 2)
        int[][] res = new int[n][n];
        int count = 1;  // 定义填充数字
        int offset = 1; // 需要控制每一条边遍历的长度,每次循环右边界收缩一位
        int i, j;

        while (loop-->0) { // 判断边界后,count从1开始
            // 模拟上侧从左到右
            for (j = starty; j < n - offset; j++) {
                res[startx][j] = count++;
                
            }

            // 模拟右侧从上到下
            for (i = startx; i < 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++;
        }

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

总结

  • 今天学习了把怎样把双指针使用的更灵活
  • 螺旋矩阵题目思路容易理解,但是循环要设置的限制条件很多,感觉掌握不太熟练
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值