您现在的位置是:首页 >技术教程 >代码随想录算法训练营第二天 | 977.有序数组的平方 ,209.长度最小的子数组 ,59.螺旋矩阵II,总结网站首页技术教程
代码随想录算法训练营第二天 | 977.有序数组的平方 ,209.长度最小的子数组 ,59.螺旋矩阵II,总结
简介代码随想录算法训练营第二天 | 977.有序数组的平方 ,209.长度最小的子数组 ,59.螺旋矩阵II,总结
977.有序数组的平方
条件:非递减顺序(严格递增顺序)
-
Java代码
- 双指针
class Solution { public int[] sortedSquares(int[] nums) { int[] res = new int[nums.length]; // Arrays.sort(nums); // 题目上只是 非递减顺序 , 可能是无序的,最好进行排序(虽然不进行排序也能通过) int left=0, right=nums.length-1; int index=nums.length-1; while (left<=right) { if (nums[left]*nums[left]>nums[right]*nums[right]) { res[index--]=nums[left]*nums[left]; left++; } else { res[index--]=nums[right]*nums[right]; right--; } } return res; } }
时间复杂度:O(n)
空间复杂度:O(n)- 暴力法(调用排序库)
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+nlogn)
空间复杂度:O(1)- 完整代码
package topic1Array; /*977. 有序数组的平方 给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。 示例 1: 输入:nums = [-4,-1,0,3,10] 输出:[0,1,9,16,100] 解释:平方后,数组变为 [16,1,0,9,100] 排序后,数组变为 [0,1,9,16,100] 来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/squares-of-a-sorted-array 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。*/ public class topic3_977 { public static void main(String[] args) { Solution solution = new topic3_977().new Solution(); int[] nums = {-4,-1,0,3,10}; PublicAPI.printArray(nums); int[] res = solution.sortedSquares(nums); PublicAPI.printArray(res); } // 双指针法 class Solution { public int[] sortedSquares(int[] nums) { int[] res = new int[nums.length]; // Arrays.sort(nums); // 题目上只是 非递减顺序 , 可能是无序的,最好进行排序(虽然不进行排序也能通过) int left=0, right=nums.length-1; int index=nums.length-1; while (left<=right) { if (nums[left]*nums[left]>nums[right]*nums[right]) { res[index--]=nums[left]*nums[left]; left++; } else { res[index--]=nums[right]*nums[right]; right--; } } return res; } } /*// 暴力法(调用排序库) 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; } }*/ }
- 双指针
209. 长度最小的子数组
滑动窗口法
- 在本题中实现滑动窗口,主要确定如下三点:
- 窗口内是什么?
- 如何移动窗口的起始位置?
- 如何移动窗口的结束位置?
窗口就是 满足其和 ≥ s 的长度最小的 连续 子数组。
窗口的起始位置如何移动:如果当前窗口的值大于s了,窗口就要向前移动了(也就是该缩小了)。
窗口的结束位置如何移动:窗口的结束位置就是遍历数组的指针,也就是for循环里的索引。
-
Java代码
- 滑动窗口法(需要维护窗口的长度)
class Solution { public int minSubArrayLen(int target, int[] nums) { int minLen = Integer.MAX_VALUE; int sum = 0; int pre=0, cur=0; for (; cur<nums.length; cur++) { sum+=nums[cur]; while (sum>=target) { // 满足条件就更新最小长度,并维护滑动窗口的总和小于 target minLen = minLen < cur-pre+1 ? minLen : cur-pre+1; sum-=nums[pre]; pre++; } } return minLen != Integer.MAX_VALUE ? minLen : 0; } }
时间复杂度:O(n) 实际是O(2n)
空间复杂度:O(1)- 完整代码
package topic1Array; /*209. 长度最小的子数组 给定一个含有 n 个正整数的数组和一个正整数 target 。 找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。 来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/minimum-size-subarray-sum 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 示例 1: 输入:target = 7, nums = [2,3,1,2,4,3] 输出:2 解释:子数组 [4,3] 是该条件下的长度最小的子数组。*/ public class topic4_209 { public static void main(String[] args) { Solution solution = new topic4_209().new Solution(); int[] nums = {2,3,1,2,4,3}; int target = 7; PublicAPI.printArray(nums); int minLen = solution.minSubArrayLen(target, nums); System.out.println(minLen); } class Solution { public int minSubArrayLen(int target, int[] nums) { int minLen = Integer.MAX_VALUE; int sum = 0; int pre=0, cur=0; for (; cur<nums.length; cur++) { sum+=nums[cur]; while (sum>=target) { // 满足条件就更新最小长度,并维护滑动窗口的总和小于 target minLen = minLen < cur-pre+1 ? minLen : cur-pre+1; sum-=nums[pre]; pre++; } } return minLen != Integer.MAX_VALUE ? minLen : 0; } } }
59.螺旋矩阵II
注意:
坚持循环不变量原则(推荐使用 左闭右开 的规则做模拟)
用循环的圈数作为判断条件,在每一圈内实现填充规则
-
模拟顺时针画矩阵的过程:
- 填充上行从左到右
- 填充右列从上到下
- 填充下行从右到左
- 填充左列从下到上
-
Java代码
- 规则模拟
class Solution { public int[][] generateMatrix(int n) { int[][] matrix = new int[n][n]; int loop=0, start=0; // 实际注意两个问题,画的圈数以及当前圈的起始点 int i=0, j=0; // i作为行,j作为列 int count=1; // 计数量,1 ~ n^2 while (loop++ < n/2) { // 用要画的圈数做为判断条件 for (i=start, j=start; j<n-loop; j++) { matrix[i][j]=count++; } for (; i<n-loop; i++) { matrix[i][j]=count++; } for (; j>=loop; j--) { matrix[i][j]=count++; } for (; i>=loop; i--) { matrix[i][j]=count++; } start++; } if (n%2==1) { // 还要注意n为奇数时,中间的点也要填充 matrix[start][start]=count; } return matrix; } }
- 完整代码
package topic1Array; /*59. 螺旋矩阵 II 给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。 示例 1: 输入:n = 3 输出:[[1,2,3],[8,9,4],[7,6,5]] 链接:https://leetcode.cn/problems/spiral-matrix-ii/*/ public class topic5_59 { public static void main(String[] args) { Solution solution = new topic5_59().new Solution(); int n = 4; int[][] matrix = solution.generateMatrix(n); PublicAPI.printArray(matrix); } class Solution { public int[][] generateMatrix(int n) { int[][] matrix = new int[n][n]; int loop=0, start=0; int i=0, j=0; int count=1; while (loop++ < n/2) { for (i=start, j=start; j<n-loop; j++) { matrix[i][j]=count++; } for (; i<n-loop; i++) { matrix[i][j]=count++; } for (; j>=loop; j--) { matrix[i][j]=count++; } for (; i>=loop; i--) { matrix[i][j]=count++; } start++; } if (n%2==1) { matrix[start][start]=count; } return matrix; } } }
数组总结
数组的经典题目
- 二分法
704.二分查找
- 可以使用暴力解法,通过这道题目,如果追求更优的算法,建议试一试用二分法,来解决这道题目
- 暴力解法时间复杂度:O(n)
- 二分法时间复杂度:O(logn)
在这道题目中我们讲到了循环不变量原则,只有在循环中坚持对区间的定义,才能清楚的把握循环中的各种细节。
- 双指针法
快慢指针:27.移除元素
977.有序数组的平方
双指针法(快慢指针法):通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。
- 暴力解法时间复杂度:O(n^2)
- 双指针时间复杂度:O(n)
数组中的元素为什么不能删除,主要是因为:
- 数组在内存中是连续的地址空间,不能释放单一元素,如果要释放,就是全释放(程序运行结束,回收内存栈空间)
双指针法(快慢指针法)在数组和链表的操作中是非常常见的,很多考察数组和链表操作的面试题,都使用双指针法。
- 滑动窗口
209.长度最小的子数组
- 暴力解法时间复杂度:O(n^2)
- 滑动窗口时间复杂度:O(n)
本题中,主要要理解滑动窗口如何移动 窗口起始位置,达到动态更新窗口大小的,从而得出长度最小的符合条件的长度。
滑动窗口的精妙之处在于根据当前子序列和大小的情况,不断调节子序列的起始位置。从而将O(n^2)的暴力解法降为O(n)。
- 模拟行为
在这道题目中,我们再一次介绍到了循环不变量原则,其实这也是写程序中的重要原则。
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。