算法训练 — 有序数组的平方 长度最小的数组

95 阅读3分钟

有序数组的平方

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

解题思路:利用前后两个指针,前后两个数字做平方后,比较大小,如果前面的大于后面说明绝对值大于后面的,放在数组的最后,前面的指针放后移动一位,后面的指针不变,重复此类操作。

注意点:存储结果的数组开始存储数据应该从最后的开始存储,原因:这里不能从0开始,必须从nums.length - 1开始,原因:存在负数,平方后全是正数,需要与最后的数做比较 (int index = nums.length - 1 )

 public static int[] sortedSquares(int[] nums) {
         if (nums == null) return new int[0];
         int start = 0, end = nums.length - 1;
         int[] result = new int[nums.length];
         int index = nums.length - 1;  // 这里不能从0开始,必须从nums.length - 1开始,原因:存在负数,平方后全是正数,需要与最后的数做比较
         while (end >= start) { // 交换数据过程
             if (nums[start] * nums[start] > nums[end] * nums[end]) {
                 result[index--] = nums[start] * nums[start];
                 ++start;
             } else {
                 result[index--] = nums[end] * nums[end];
                 --end;
             }
         }
         return result;
     }

长度最小的数组

长度最小的数组

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

解题思路:

暴力解法:通过两个for循环来列举所有情况,然后选取其中最小的数组

窗口滑动方法(描述 的有问题,等待):从组数的起点,选取两个点ab,然后a点往前移动,叠加所有的移动的下标。如果大于等于目标值,这个ab是一个临时窗口,长度可能不是最小,然后b往后移动寻找最小的长度,滑动到<目标值的时候,往后移动a点,直到>=目标值,选取a-b+1的最小值

// todo 等深刻理解后,再次精确描述此段文字

  public static int minSubArrayLen(int target, int[] nums) {
         int left = 0;
         int sum = 0;
         int result = Integer.MAX_VALUE;
         for (int right = 0; right < nums.length; right++) {
             sum += nums[right];
             while (sum >= target) { // 表示当前的窗口的数字大于目标值,同时这个可以控制left指针向后滑动
                 result = Math.min(result, right - left + 1);
                 System.out.println("left = " + nums[left] + "::::right " + nums[right]);
                 sum -= nums[left++];
             }
         }
         return result == Integer.MAX_VALUE ? 0 : result;
     }

螺旋矩阵

[59. 螺旋矩阵 II ]

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

   public static int[][] generateMatrix(int n) {
         int[][] res = new int[n][n];
 ​
         // 循环次数
         int loop = n / 2;
 ​
         // 定义每次循环起始位置
         int startX = 0;
         int startY = 0;
 ​
         // 定义偏移量
         int offset = 1;
 ​
         // 定义填充数字
         int count = 1;
 ​
         // 定义中间位置
         int mid = n / 2;
         while (loop > 0) {
             int i = startX;
             int j = startY;
 ​
             // 模拟上侧从左到右
             for (; j<startY + n -offset; ++j) {
                 res[startX][j] = count++;
             }
             // 模拟右侧从上到下
             for (; 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++;
             }
             loop--;
             startX += 1;
             startY += 1;
 ​
             offset += 2;
         }
 ​
         if (n % 2 == 1) {
             res[mid][mid] = count;
         }
 ​
         return res;
     }