有序数组的平方
给你一个按 非递减顺序 排序的整数数组
nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
示例:
输入:nums = [-4,-1,0,3,10] 输出:[0,1,9,16,100] 解释:平方后,数组变为 [16,1,0,9,100] 排序后,数组变为 [0,1,9,16,100]
这里使用快慢指针的方式解答,从题目上来看,最大值只会出现在最左边或者最右边,同时向中间靠拢,这时我们就可以用两个指针,一个从左往右移动,一个从右往左移动,然后比较左右两边结果的大小。然后考虑到题目需要从小到大排序,所以需要事先定义一个数组,来插入结果数据。
public static int[] sortedSquares(int[] nums) {
int[] result = new int[nums.length];
int resultIndex = nums.length - 1;
for (int i = 0, j = nums.length - 1; i <= j;) {
int resultFromStart = nums[i] * nums[i];
int resultFromEnd = nums[j] * nums[j];
if(resultFromStart >= resultFromEnd) {
result[resultIndex] = resultFromStart;
i ++;
resultIndex --;
} else {
result[resultIndex] = resultFromEnd;
j --;
resultIndex --;
}
}
return result;
}
长度最小的子数组
解题的关键在于滑动窗口的处理,类似于双指针,通过双指针控制开始和结束索引的位置来避免双for循环带来的性能损失。
public static int minSubArrayLen(int target, int[] nums) {
int i = 0;
int sumValue = 0;
int minLen = Integer.MAX_VALUE;
for (int j = 0; j < nums.length; j++) {
sumValue += nums[j];
while (sumValue >= target) {
int len = j - i + 1;
minLen = Integer.min(len, minLen);
sumValue = sumValue - nums[i];
i++;
}
}
if (minLen == Integer.MAX_VALUE) {
return 0;
}
return minLen;
}
这里i是表示窗口开始的指针,j表示窗口结束的指针。先通过累加达到所要求的target,然后移动开始的指针来缩小窗口的大小,直到求得最小子数组,然后继续移动j。
螺旋矩阵
在处理边界的时候要十分小心,同时遵循着左闭右开的原则,保证矩阵中的每个格子都有值填充进去。
if(n == 1) {
return new int [][] {new int[]{1}};
}
int startX = 0; // 每一轮循环开始的横坐标index
int startY = 0; // 每一轮循环开始的纵坐标index
int offset = 1; // 完成一轮循环之后进行缩进
int count = 1; //数字从1开始
int[][] results = new int[n][n];
int round = n/2; // 循环轮数,如果是偶数,循环n/2 次即可,如果是奇数,需要补充中间的数
int i,j;
while (round >= 1) {
// 以左闭右开的方式遍历填充数据
// 从左往右填充
for (j = startY; j < n - offset; j++) {
results[startX][j] = count ++;
}
// 从上往下填充
for (i = startX; i < n - offset; i++) {
results[i][j] = count ++;
}
// 从右往左填充
for (; j > startY; j--) {
results[i][j] = count ++;
}
// 左侧的从下网上填充
for (; i > startX; i--) {
results[i][j] = count ++;
}
// 缩进,进行内部的循环
startX ++;
startY ++;
offset ++;
round --;
}
if (n % 2 == 1) {
results[startX][startY] = count;
}
return results;
}