代码随想录算法训练营第二天 | 977、209、59
977.有序数组的平方
题目描述
给你一个按非递减顺序排序的整数数组nums,返回每个数字的平方组成的新数组,要求也按非递减顺序排序。
示例1:
输入:nums=[−4,−1,0,3,10]nums = [-4,-1,0,3,10]nums=[−4,−1,0,3,10]
输出:[0,1,9,16,100][0,1,9,16,100][0,1,9,16,100]
示例1:
输入:nums=[−7,−3,2,3,11]nums = [-7,-3,2,3,11]nums=[−7,−3,2,3,11]
输出:[4,9,9,49,121][4,9,9,49,121][4,9,9,49,121]
思路
题目中非递减顺序排序的整数数组,生成的新数组也要按照非递减顺序排序。在本题中,针对结果来讲,给出的数组是两段或一段有序的数组。若数组中全部为正整数,则平方数组为非递减顺序;若数组中全部为负整数,则平方数组为非递增顺序;若同时存在负整数和正整数,则平方数组在0之前为非递增,在0之后为非递减顺序。
那么首先,需要对不同情况分类讨论;
针对同时存在负整数和正整数的情况,使用双指针的方式进行比较,并根据大小关系来判断其位置。
解法
class Solution {
public int[] sortedSquares(int[] nums) {
int neg = -1;
int n= nums.length;
for(int i=0;i<n;i++){
if(nums[i]<0){
neg = i;
}
else{
break;
}
}
int i=neg,j=neg+1;
int[] ans = new int[n];
int index = 0;
while(i>=0 || j<n){
if(i<0){
ans[index++] = nums[j]*nums[j];
j++;
}
else if(j == n){
ans[index++] = nums[i]*nums[i];
i--;
}
else if(nums[i]*nums[i] > nums[j]*nums[j]){
ans[index++] = nums[j]*nums[j];
j++;
}
else{
ans[index++] = nums[i]*nums[i];
i--;
}
}
return ans;
}
}
总结
1、注意分类讨论,全是正整数或负整数的情况可以先行判断。
2、对于有正有负的情况,注意找到分界点并使用双指针在分界点两侧移动寻找相等。
209. 长度最小的子数组
题目描述
给定一个含有 n 个正整数的数组和一个正整数 target 。
找出该数组中满足其和 ≥ target 的长度最小的连续子数组 [numsl, numsl+1, …, numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。
示例1:
输入:target=7,nums=[2,3,1,2,4,3]target = 7, nums = [2,3,1,2,4,3]target=7,nums=[2,3,1,2,4,3]
输出:222
示例2:
输入:target=4,nums=[1,4,4]target = 4, nums = [1,4,4]target=4,nums=[1,4,4]
输出:111
示例3:
输入:target=11,nums=[1,1,1,1,1,1,1,1]target = 11, nums = [1,1,1,1,1,1,1,1]target=11,nums=[1,1,1,1,1,1,1,1]
输出:000
思路
题目要求找到和大于等于目标值的长度最小连续子数组,则能够想到使用滑动窗口的方法。
在滑动窗口中,右边界扩张,左边界撤销。
解法
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int sum = 0,left = 0;
int window = Integer.MAX_VALUE;
for(int right=0;right<nums.length;right++){
sum += nums[right];
while(sum >= target){
window = Math.min(window,right-left+1);
sum -= nums[left++];
}
}
return window == Integer.MAX_VALUE ? 0:window;
}
}
总结
本题中最重要的是能够看出应该使用滑动窗口求解。但在对滑窗的应用上并没有太多的坑,只需按部就班即可。
59. 螺旋矩阵Ⅱ
题目描述
给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。
示例1:
输入:n=3n=3n=3
输出:[[1,2,3],[8,9,4],[7,6,5]][[1,2,3],[8,9,4],[7,6,5]][[1,2,3],[8,9,4],[7,6,5]]
示例2:
输入:n=1n=1n=1
输出:[[1]][[1]][[1]]
思路
本题在总体思路上很简单,只需模拟生成过程,一圈一圈地放置元素即可。但在细节思路上,会发现有很多需要注意的问题,首要的就是每一行每一列在填充时的规则,是左闭右闭、左闭右开还是左开右闭。这里我选择的是左闭右开原则,不仅可以从原始位置开始便利,而且在行和列的角度上更具有对称感。
解法
class Solution {
public int[][] generateMatrix(int n) {
int loop = 0;
int[][] result = new int[n][n];
int count = 1;
int start = 0;
int i,j;
while(loop++ < n/2){
for(j=start;j<n-loop;j++){
result[start][j] = count++;
}
for(i = start;i<n-loop;i++){
result[i][j] = count++;
}
for(;j>=loop;j--){
result[i][j] = count++;
}
for(;i>=loop;i--){
result[i][j] = count++;
}
start++;
}
if(n%2 == 1){
result[start][start] = count;
}
return result;
}
}
总结
对于本题来说,最重要的是要能够明确遍历时的规则,约定好每一行每一列在循环时的边界范围。此外,还有一个需要注意的点是,是否需要补充最中心的元素,在本题前两次的提交中我就忘记了这个而导致错误。
文章介绍了三个算法问题的解决方案:1)有序数组的平方,通过双指针处理正负数情况得到非递减平方数组;2)长度最小的子数组,使用滑动窗口找到和大于等于目标值的最小子数组;3)螺旋矩阵II,模拟生成过程,按螺旋顺序填充矩阵元素。





