①、有序数组的平方
给你一个按 非递减顺序 排序的整数数组
nums
,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
力扣(LeetCode)链接:https://leetcode.cn/problems/squares-of-a-sorted-array
事例:
输入:nums = [-4,-1,0,3,10]
输出:[0,1,9,16,100]
解释:平方后,数组变为 [16,1,0,9,100]
排序后,数组变为 [0,1,9,16,100]
思路:
由于数组有正负值,负数的平方可能大于正数,即一般情况,数组的平方大小是从左右两端从中间收缩的,故可以采用双指针做法。创建一个结果数组res,存放结果集,用左右指针left和right分别往中间靠,比较,把小的平方值放入res即可。
public int[] sortedSquares(int[] nums) {
int n = nums.length;
int left = 0;
int right = n - 1;
int[] res = new int[n];
int count = right; //记录res的下标值
while(left <= right){
//循环判断 加=是要判断右边的值,即左闭右闭
int a = nums[left] * nums[left];
int b = nums[right] * nums[right];
if(a <= b){
//负数的平方小于正数
res[count--] = b;
right--;
}else{
//负数的平方大于正数
res[count--] = a;
left++;
}
}
return res;
}
②、长度最小的子数组
给定一个含有 n 个正整数的数组和一个正整数 target 。
找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。
力扣(LeetCode)链接:https://leetcode.cn/problems/minimum-size-subarray-sum
事例:
输入:target = 7, nums = [2,3,1,2,4,3] 输出:2 解释:子数组 [4,3]是该条件下的长度最小的子数组。
思路:
该题得用滑动窗口做法,滑动窗口与双指针类似,有两个指向,但循环条件以及应用不同。滑动窗口需要保持end指针始终大于start,保证两指针中间有元素,当中间的元素满足条件时,再剔除多余的元素以求最优解。
以该题目为例: 创建两个指针start end都为0,end往右走,当中间元素满足条件(>= target)时,start往右走(缩小中间范围,求最小的子数组)。当end遍历完时,得到的最小值就是该数组满足条件的最小子数组。
代码:
public int minSubArrayLen(int target, int[] nums) {
if(nums == null){
return 0;
}
int res = Integer.MAX_VALUE;
int start = 0;
int end = 0;
int sum = 0;
for(;end < nums.length;end++){
sum += nums[end];
while(sum >= target){
res = Math.min(res,end - start + 1);
sum -= nums[start];
start++;
}
}
return res == Integer.MAX_VALUE ? 0 : res;
}
力扣(LeetCode)链接:https://leetcode.cn/problems/spiral-matrix-ii/
③、螺旋矩阵 Ⅱ
给你一个正整数
n
,生成一个包含1
到n2
所有元素,且元素按顺时针顺序螺旋排列的n x n
正方形矩阵matrix
。
事例:
输入:n = 3 输出:[[1,2,3],[8,9,4],[7,6,5]
代码:
public int[][] generateMatrix(int n) {
if(n == 1){
return new int[][]{{1}};
}
int[][] res = new int[n][n];
int x = 0;
int y = 0;
int offset = 1; //循环圈数
int count = 1;
int round = 0;
while(round < n / 2){
int i = x;
int j = y;
for(;j < n - offset;j++){
//从左到右赋值
res[i][j] = count++;
}
for(;i < n - offset;i++){
//从上到下赋值
res[i][j] = count++;
}
for(;j > y;j--){
//从右到左赋值
res[i][j] = count++;
}
for(;i > x;i--){
//从左到右赋值
res[i][j] = count++;
}
//处理完一圈
round++;
offset++;
x++;
y++;
}
if(n % 2 != 0){
res[n / 2][n / 2] = n * n;
}
return res;
}
该题需要顺时针赋值二维数组中的每个值,由于每次循环一圈都操作了上下、左右两边,故循环此数为n / 2,在赋值过程中,需要分别处理左右上下边界的问题,故要统一好规则,这里用左闭右开的原则,即每一行都处理开头到最后第二个,留下最后一个给下一行处理。