力扣977. 有序数组的平方
题目描述
解题思路
自己解题
class Solution {
public int[] sortedSquares(int[] nums) {
for (int i = 0; i < nums.length; i++) {
nums[i] = nums[i] * nums[i];
}
int[] res = new int[nums.length];
int left = 0;
int right = nums.length - 1;
int k = right;
while (k >= 0) {
if (nums[left] < nums[right]) {
res[k] = nums[right];
right--;
k--;
} else {
res[k] = nums[left];
left++;
k--;
}
}
return res;
}
}
参考解题
class Solution {
public int[] sortedSquares(int[] nums) {
int right = nums.length - 1;
int left = 0;
int[] result = new int[nums.length];
int index = result.length - 1;
while (left <= right) {
if (nums[left] * nums[left] > nums[right] * nums[right]) {
// 正数的相对位置是不变的, 需要调整的是负数平方后的相对位置
result[index--] = nums[left] * nums[left];
++left;
} else {
result[index--] = nums[right] * nums[right];
--right;
}
}
return result;
}
}
总结
1.注意索引和数组长度之间的关系
2.数组其实是有序的, 只不过负数平方之后可能成为最大数了。那么数组平方的最大值就在数组的两端,不是最左边就是最右边,不可能是中间。此时可以考虑双指针法了,left指向起始位置,right指向终止位置。
3.定义一个新数组res,和res数组一样的大小,从高位索引逐步往下减一,比较
力扣209.长度最小的子数组
题目描述
解题思路
右端口一直向右移动,直到sum >= target时,首先记录当前窗口的大小,然后开始考虑移动左端口,每移动一次端口,相应计算窗口内元素之和sum
左端口什么时候停止移动?直到不满足sum>=target时。此时接着移动右端口。
自己解题
class Solution {
// 滑动窗口
public int minSubArrayLen(int target, int[] nums) {
int left = 0;
int sum = 0;
int result = nums.length;
for (int right = 0; right < nums.length; right++) {
sum += nums[right];
while (sum >= target) {
result = Math.min(result, right - left + 1);//调用Math工具类中的方法 取小的的
sum -= nums[left++];
}
}
return result == nums.length ? 0 : result;
}
}
参考解题
class Solution {
// 滑动窗口
public int minSubArrayLen(int s, int[] nums) {
int left = 0;
int sum = 0;
int result = Integer.MAX_VALUE;
for (int right = 0; right < nums.length; right++) {
sum += nums[right];
while (sum >= s) {
result = Math.min(result, right - left + 1);
sum -= nums[left++];
}
}
return result == Integer.MAX_VALUE ? 0 : result;
}
}
总结
窗口内元素:保持窗口内数值总和大于或等于S的长度最小的连续子数组
窗口的起始位置如何移动:如果当前窗口的值大于s了,窗口就要向前移动了(也就是该缩小了)。
窗口的结束位置如何移动:窗口的结束位置就是遍历数组的指针,也就是for循环里的索引。
力扣59.螺旋矩阵
题目描述
解题思路
循环不变量:是每条边的处理规则
左闭右开:不去处理最后一个节点,而是把它当最下一条边的起始节点
模拟顺时针画矩阵的过程:
- 填充上行从左到右
- 填充右列从上到下
- 填充下行从右到左
- 填充左列从下到上
自己解题
两个for循环 暴力解法没参考意义
参考解题
class Solution {
public int[][] generateMatrix(int n) {
int loop = 0; // 控制循环次数
int[][] res = new int[n][n];
int start = 0; // 每次循环的开始点(start, start)
int count = 1; // 定义填充数字
int i, j;
while (loop++ < n / 2) { // 判断边界后,loop从1开始,转的圈数n/2
// 模拟上侧从左到右
for (j = start; j < n - loop; j++) {
res[start][j] = count++;
}
// 模拟右侧从上到下
for (i = start; i < n - loop; i++) {
res[i][j] = count++;
}
// 模拟下侧从右到左
for (; j >= loop; j--) {
res[i][j] = count++;
}
// 模拟左侧从下到上
for (; i >= loop; i--) {
res[i][j] = count++;
}
start++;//一圈转完,起始点更改
}
if (n % 2 == 1) {
res[start][start] = count;
}
return res;
}
}
补充
若n为奇数,最后一个元素单独处理
if (n % 2 == 1) {
res[start][start] = count;
}
ps:文中部分图片和代码来自代码随想录和Leetcode官网