977.有序数组的平方
给你一个按 非递减顺序 排序的整数数组 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+nlogn))
先算平方,再排序
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))
原数组是从小到大排序的,平方的最大值一定在原数组的两侧,因此只需要在左右两边各放一个指针,平方大的数放在数组的后面,从后往前依次放。
class Solution {
public int[] sortedSquares(int[] nums) {
//双指针思想,数打的一定在两边
int left=0;
int len=nums.length;
int right=len-1;
int count=len-1;
int [] array=new int[len];
while(left<=right){
if(nums[left]*nums[left]>nums[right]*nums[right]){
array[count--]=nums[left]*nums[left];//由大到小排序,所以从后往前放
left++;
}else {
array[count--]=nums[right]*nums[right];
right--;
}
}
return array;
}
}
209.长度最小的子数组
题目描述:
给定一个含有 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
暴力解法(O(n2))
暴力解法的时间复杂度是O(n2)。一个循环遍历数组的每一个位置作为起始遍历位置,另一个循环从起始位置往后面找,直到找到第一个大于等于target的位置。另外由于是寻找最短的长度,所以初始的最小长度可以设置为一个很大的数字,用于更新最小长度。
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int len = nums.length;
int minlength = Integer.MAX_VALUE;
for (int begin = 0; begin < len; begin++) {
int sum = 0;// 每一行的sum的值都是从新开始计算的
for (int end = begin; end < len; end++) {
sum += nums[end];
if (sum >=target) {
int length = end - begin + 1;
minlength = minlength > length ? length : minlength;//放在if里面,放在外面length可能没有定义
}
}
}
if (minlength == Integer.MAX_VALUE) {
return 0;
} else
return minlength;
}
}
滑动窗口(O(n))
滑动窗口的循环只遍历一次数组,时间复杂度为O(n)。关键是遍历的是终止位置,而不是从起始位置向后面找。循环的条件是找到第一个sum大于等于target的位置,更新最短长度。然后在循环内让起始位置向后挪一位,同时sum-nums[起始位置]。注意的是要找到最短长度,所以用while循环不断去更新起始位置,直到不满足大于等于target的条件,才退出while循环,并让j的值向后挪一位。
class Solution {
public int minSubArrayLen(int target, int[] nums) {
// 滑动窗口
//要点1:终止位置作为循环条件
int len=nums.length;
int i=0;
int sum=0;
int minlen=Integer.MAX_VALUE;
for(int j=0;j<len;j++){
sum+=nums[j];
while(sum>=target){//while循环,不能使用if,因为大于就一直让i往后面找
minlen=minlen>j-i+1?j-i+1:minlen;
sum-=nums[i];//往后移动所以要减i位置的值
i++;
}
}
return minlen==Integer.MAX_VALUE?0:minlen;
}
}
59.螺旋矩阵II
题目描述
给你一个正整数 n
,生成一个包含 1
到 n2
所有元素,且元素按顺时针顺序螺旋排列的 n x n
正方形矩阵 matrix
。
示例 1:
输入:n = 3 输出:[[1,2,3],[8,9,4],[7,6,5]]
示例 2:
输入:n = 1 输出:[[1]]
螺旋矩阵的难点一:循环条件
这里选择的是循环的圈数,选取的方法很巧妙,奇数可以不用更新最后一圈,偶数直接都更新完
难点二:边界条件,这里选择的相当于一个左闭右开区间,右边的边界总是取不到,4个for 循环保持统一。循环的时候为了不断更新数组,循环里使用变化的量,start和end,而不是n-1和0.
class Solution {
public int[][] generateMatrix(int n) {
int[][] mat=new int [n][n];
int start=0;
int end=n-1;
int count=1;
int loop=1;
//左闭右开区间
while(loop<=n/2){
for(int j=start;j<end;j++){
mat[start][j]=count++;
}
for(int i=start;i<end;i++){
mat[i][end]=count++;
}
for(int j=end;j>start;j--){
mat[end][j]=count++;
}
for(int i=end;i>start;i--){
mat[i][start]=count++;
}
start++;
end--;
loop++;//别忘了更新循环条件
}
if(n%2==1){
mat[n/2][n/2]=n*n;
}
return mat;
}
}
第一章数组小结
数组一开始就确定了大小,后面增删插很麻烦。确定的长度可以考虑双指针、滑动窗口、二分查找。注意不要超出索引。
另外,附上代码随想录训练营的总结图和文章链接