LeetCode 977.有序数组的平方
题目描述:
给你一个按 非递减顺序 排序的整数数组 nums
,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
输入:nums = [-4,-1,0,3,10]
输出:[0,1,9,16,100]
解释:平方后,数组变为 [16,1,0,9,100]
排序后,数组变为 [0,1,9,16,100]
题目链接:力扣
解题思路:
- 看到该题后,注意到非递减顺序,确定该类型题是有序数组。并且要求返回每个数组的平方组成的新数组也要求排序,表面该题肯定是要进行遍历。浮现在脑海的第一个想法是直接全部平方再排序。
- 第二个思路就是使用双指针和第二个数组进行解决。左右两个指针进行对比,平方数大的塞入到新的数组中。
双指针遍历写法:
public class Solution {
public int[] SortedSquares(int[] nums) {
int[] result = new int[nums.Length];
int k = nums.Length-1;
for(int i = 0,j = nums.Length-1;i<=j; ){
if(nums[i]*nums[i] >= nums[j] *nums[j]){
result[k--] = nums[i] * nums[i++];
}else{
result[k--] = nums[j]*nums[j--];
}
}
return result;
}
}
复杂度:
时间复杂度:O(n)
空间复杂度: O(n)
总结:
遇到这种输出有序数组的,十有八九是要排序,先考虑双指针等方法解题。
LeetCode 209.长度最小的子数组
题目描述:
给定一个含有 n
个正整数的数组和一个正整数 target
。
找出该数组中满足其和 ≥ target
的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr]
,并返回其长度。如果不存在符合条件的子数组,返回 0
。
输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。
解题思路:
- 自己心路历程:看到题目后,首先想到的是排序后,从后向前推进。再仔细阅读后,该题目要求该数组满足条件的连续子数组。所以,只能放弃,选择暴力解法。外循环为左边界,内循环为有边界,记录满足条件的数据,完成题目。
- 参考优质解法:看了讲解和以前刷题时提交的代码,发现使用动态窗口的方法来解决更好。动态窗口本质上是暴力解法的优化,让左边界随动,来达到目的。让右边界变化,计算左边界到右边界的和,当和大于目标值时,则让左边界右移。记录满足条件的最小目标值。ps:内部循环要使用while进行,让其在右边界不动的情况下,不断修改左边界。
动态窗口法:
public class Solution {
public int MinSubArrayLen(int target, int[] nums) {
int result = int.MaxValue;
int sum = 0;
for(int i = 0,j = 0;j <= nums.Length-1;){
sum += nums[j];
while(sum>= target){
result = (j-i+1) < result?(j-i+1):result;
sum-=nums[i];
i++;
}
j++;
}
return result == int.MaxValue?0:result;
}
}
复杂度:
时间复杂度:O(n)
空间复杂度: O(1)
总结:
遇到计算连续数组的题目,可以首先考虑尝试动态窗口的思路来解决问题。
LeedCode 59螺旋数组
题目描述:
给你一个正整数 n
,生成一个包含 1
到 n2
所有元素,且元素按顺时针顺序螺旋排列的 n x n
正方形矩阵 matrix
。
输入:n = 3
输出:[[1,2,3],[8,9,4],[7,6,5]]
解题思路:
- 惭愧,虽然之前做过一遍,但是这次一看到,毫无思路。看了讲解和上次的代码后,发现本题目考察的就是边界条件的问题,从左到右从上到下,进行填充。
解法:
public class Solution {
public int[][] GenerateMatrix(int n) {
int[][] result = new int[n][];
for(int i=0;i<n;i++){
result[i] = new int[n];
}
int start = 0;
int end = n -1;
int count = 1;
while(count < n*n){
for(int i = start; i<end;i++ ) result[start][i]=count++;
for(int i=start;i <end;i++) result[i][end] = count++;
for(int i= end; i > start;i-- ) result[end][i] = count++;
for(int i = end;i>start;i--) result[i][start] = count++;
start++;
end--;
}
if(n%2 == 1){
result[n/2][n/2] = count;
}
return result;
}
}
复杂度:
时间复杂度:O(n^2)
空间复杂度 : O(n^2)
数组篇总结
- 这两天来,在数组中常用到的思想解法:二分法,双指针法,滑动窗口法。
- 二分法:中要注意的就是区间的定义。其衍生的解决问题有寻找左边界,寻找右边界。其核心思想就是压缩右边界或压缩左边界。
- 双指针法:除了正常使用左右各设置外,还要考虑快慢指针来解决问题。
- 滑动窗口:根据当前的子序列的大小和情况,不断调节子序列的起始位置。