首页 > 编程语言 >代码随想录算法Day02| 977.有序数组的平方 ,209.长度最小的子数组 ,59.螺旋矩阵II

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

时间:2023-02-02 22:34:32浏览次数:70  
标签:977 target nums int 随想录 ++ result 数组

977.有序数组的平方

题目链接:977. 有序数组的平方 - 力扣(LeetCode)

题目

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

示例 1:

输入:nums = [-4,-1,0,3,10]
输出:[0,1,9,16,100]
解释:平方后,数组变为 [16,1,0,9,100]
   排序后,数组变为 [0,1,9,16,100]


示例 2:

输入:nums = [-7,-3,2,3,11]
输出:[4,9,9,49,121]

 

思路

  暴力法:

    每个数开平方在排序。

    时间复杂度 : O(n + n * logn) 

  双指针法:

    题目中数组是有序的,同时负数开平方以后可能会变成最大数。由此可以得出数组的平方的最大值只可能在数组的左右两端。

    因此可以采用双指针法,一个左指针在数组最左端 ( left = 0),一个右指针在数组最右端 ( right = 0) ,两边平方进行比较,较大的赋值到新数组的末尾,同时相应的指针移动。

    时间复杂度: O(n)

代码

  暴力法:略

  双指针法:

 1 class Solution {
 2     public int[] sortedSquares(int[] nums) {
 3         int[] result = new int[nums.length];
 4         int left = 0; // 左指针
 5         int right = nums.length - 1; // 右指针
 6         int index = nums.length - 1; // 当前新数组的索引位置
 7         while(left <= right){ // 注意这里要left <= right,因为最后要处理两个元素
 8             if(nums[left] * nums[left] > nums[right] * nums[right]){
 9                 result[index--] = nums[left] * nums[left];
10                 ++left;
11             }else{
12                 result[index--] = nums[right] * nums[right];
13                 --right;
14             }
15         }
16         return result;
17     }
18 }

 

209.长度最小的子数组

题目链接:209. 长度最小的子数组 - 力扣(LeetCode)

题目

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

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

 

示例 1:

输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。

示例 2:

输入:target = 4, nums = [1,4,4]
输出:1

示例 3:

输入:target = 11, nums = [1,1,1,1,1,1,1,1]
输出:0

思路

暴力法:

  通过两个for不断寻找条件符合的子序列。

  时间复杂度: O(n ^ 2)

滑动窗口:

首先确认三点:

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

先记录前面几个元素的和,当满足大于等于target时,就开始缩减窗口大小直到小于target,记录此时极限的窗口大小。

  时间复杂度: O(n)

代码

暴力法:

 1 class Solution {
 2     public int minSubArrayLen(int target, int[] nums) {
 3         int result = Integer.MAX_VALUE; // 最终的结果
 4         int sum = 0; // 子序列的数值之和
 5         int subLength = 0; // 子序列的长度
 6         for (int i = 0; i < nums.length; i++) { // 设置子序列起点为i
 7             sum = 0;
 8             for (int j = i; j < nums.length; j++) { // 设置子序列终止位置为j
 9                 sum += nums[j];
10                 if (sum >= target) { // 一旦发现子序列和超过了s,更新result
11                     subLength = j - i + 1; // 取子序列的长度
12                     result = result < subLength ? result : subLength;
13                     break; // 因为我们是找符合条件最短的子序列,所以一旦符合条件就break
14                 }
15             }
16         }
17         // 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列
18         return result == Integer.MAX_VALUE ? 0 : result;        
19     }
20 }

滑动窗口:

 1 class Solution {
 2     public int minSubArrayLen(int target, int[] nums) {
 3         int result = Integer.MAX_VALUE;
 4         int start = 0; // 滑动窗口起始位置
 5         int sum = 0; // 滑动窗口数值之和
 6         
 7         for(int end = 0;end < nums.length;end++){
 8             sum += nums[end];
 9             // 当sum > target 时开始滑动窗口更新
10             while(sum >= target){
11                 int subLength = end - start + 1; // 当前滑动窗口的长度
12                 result = result > subLength ? subLength : result; 
13                 sum -= nums[start++]; // 变更起始位置 
14             }
15         }
16         //如果结果还是初始说明不存在符合条件的子数组,则返回0.
17         return result == Integer.MAX_VALUE ? 0 : result;
18     }
19 }

 

59.螺旋矩阵II 

题目链接:59. 螺旋矩阵 II - 力扣(LeetCode)

题目

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

 

示例 1:

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

示例 2:

输入:n = 1
输出:[[1]]

思路

模拟顺时针画矩阵的过程:

  • 填充上行从左到右
  • 填充右列从上到下
  • 填充下行从右到左
  • 填充左列从下到上

注意:

  • n/2即为要走的圈数
  • 到第二圈后 起始点变为(1,1),以此类推
  • n为奇数的时候,中心点单独赋值
  • 画边时,左闭右开

代码:

 1 class Solution {
 2     public int[][] generateMatrix(int n) {
 3         int loop = 0;  // 控制循环次数
 4         int[][] res = new int[n][n];
 5         int start = 0;  // 每次循环的起始点(start, start)
 6         int count = 1;  // 定义填充数字
 7         int i, j; // i 代表行,j 代表列
 8 
 9         while (loop++ < n / 2) { // 判断边界后,loop从1开始
10             // 模拟上侧从左到右,注意 此时 loop = 1
11             for (j = start; j < n - loop; j++) {
12                 res[start][j] = count++;
13             }
14 
15             // 模拟右侧从上到下
16             for (i = start; i < n - loop; i++) {
17                 res[i][j] = count++;
18             }
19 
20             // 模拟下侧从右到左
21             for (; j >= loop; j--) {
22                 res[i][j] = count++;
23             }
24 
25             // 模拟左侧从下到上
26             for (; i >= loop; i--) {
27                 res[i][j] = count++;
28             }
29 
30             //更新下次起始点
31             start++;
32         }
33         // n 为奇数时,中心值单独赋值
34         if (n % 2 == 1) {
35             res[start][start] = count;
36         }
37         return res;
38     }
39 }

 

标签:977,target,nums,int,随想录,++,result,数组
From: https://www.cnblogs.com/xpp3/p/17087621.html

相关文章