977. 有序数组的平方
1. 题目
给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
2. 自己的思考
先数组平方,然后再使用排序算法排序。最后的时间复杂度、空间复杂度与排序算法有关。
3. 代码
class Solution {
public int[] sortedSquares(int[] nums) {
for (int i = 0; i < nums.length; i++) {
nums[i] = nums[i] * nums[i];
}
System.out.println("1"+Arrays.toString(nums));
// 遍历的轮数
for (int i = 0; i < nums.length - 1; i++) {
// 应该遍历到的最后一个元素的前一个元素
for (int j = 0; j < nums.length -1 - i; j++) {
if (nums[j] > nums[j+1]) {
int temp = nums[j+1];
nums[j+1] = nums[j];
nums[j] = temp;
}
}
}
System.out.println(Arrays.toString(nums));
return nums;
}
}
209. 长度最小的子数组
1. 题目
给定一个含有 n 个正整数的数组和一个正整数 target 。
找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [nums], numsl+1, …, numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。
2. 自己的思考
2.1 暴力解法
从第一个数字,开始遍历,记录 >=target 的数组的长度。每次更新最小长度。如果从当前数字一直加到最后一个数,都不满足 >= target,那么就结束遍历。如果最小长度<=arr.length,就返回最小长度;否则就返回0。
2.2 双指针法
左右两个指针,左指针开始一直向右移动,当记录 < target 时,就不再移动左指针;右指针开始一直向左移动,当记录 < target 时,就不再移动右指针。如果左右指针没有移动,并且记录 < target,就返回0,否则就返回最终的左右指针之间的长度。
3. 代码
3.1 暴力解法
public int minSubArrayLen2(int target, int[] nums) {
// 数组长度
int n = nums.length;
// 最小长度
int minLeng = Integer.MAX_VALUE;
// 累计和
int sum = 0;
// 满足条件的长度
int leng = 0;
// 边界条件
if (n == 0) {
return -1;
}
// 遍历的趟数
for (int j = 0; j < n; j++) {
// 每趟从哪个数字开始
for (int i = j; i < n; i++) {
sum += nums[i];
leng++;
// 查询出了最小长度
if (sum >= target && leng < minLeng) {
minLeng = leng;
}
// 没有最小长度
if (leng == n && sum < target) {
return 0;
}
}
sum = 0;
leng = 0;
}
// 存在最小长度
if (minLeng < Integer.MAX_VALUE) {
return minLeng;
}
return -1;
}
3.2 双指针法
// 双指针法
public int minSubArrayLen3(int target, int[] nums) {
// 最小长度
int minLength = Integer.MAX_VALUE;
// 子序列总和
int sum = 0;
for (int j = 0, i = 0; j < nums.length; j++) {
// 计算子序列总和
sum += nums[j];
// 滑动窗口
while (sum >= target) {
// 计算最小长度
minLength = Math.min(minLength, j - i + 1);
// 不断的变更子序列的起始位置
sum -= nums[i++];
}
}
return minLength == Integer.MAX_VALUE ? 0 : minLength;
}
4. 遇到的问题
4.1 双指针法
1. 什么是滑动窗口
只需要一个 for 循环
窗口里的内容是什么:满足条件的数据
如何移动起始位置:当满足 sum >= target 的时候,就可以删除起始位置的数据
如何移动结束位置:for 循环作为结束位置。通过不断的减去起始位置的数据,来保证滑动窗口中有长度最小的子数组。
59. 螺旋矩阵 II
1. 题目
给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。
2. 遇到的问题
2.1 什么时候结束循环
螺旋矩阵,是一圈一圈的创建矩阵。我们只需要知道需要循环几圈。
2.2 i,j 和 startx,starty 的区别
i,j 是用来遍历矩阵的;而 startx,starty 是用来记录每圈循环矩阵的开始位置。
2.3 应该以什么样的顺序循环,每次循环多少
就是按照顺时针来进行循环的。为了使边界的判断更加统一,采用左闭右开,每个边界点都作为起始点。
2.4 每轮循环的个数不同,如何解决
设置偏移值 offset。刚开始偏移值 offset = 1,之后 offset 逐渐增大。
2.5 每轮循环的起始位置是
nums[startx][starty],y = starty,y 不断发生改变
2.6 奇数个元素,其中心位置如何确定
nums[startx][starty]
3. 代码
public class Solution {
public static void main(String[] args) {
Solution solution = new Solution();
int n = 6;
int[][] nums = solution.generateMatrix(n);
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
System.out.print(nums[i][j] + "\t");
}
System.out.println();
}
}
/**
* 什么时候结束循环?
* 转几圈能把矩阵填满
*
* @param n
* @return
*/
public int[][] generateMatrix(int n) {
// 结果数组
int[][] nums = new int[n][n];
// 圈数
int turns = 0;
// 起始位置
int startx = 0, starty = 0;
// 循环的位置
int i = 0, j = 0;
// 偏移值
int offset = 1;
// 数值
int count = 1;
// 循环的圈数
while (turns < n/2) {
// 从左到右
for (j = starty; j < n - offset; j++) {
// 这里 i 应该为 startx,即 x 的起始位置
nums[startx][j] = count++;
}
// 从右到下
for (i = startx; i < n - offset; i++) {
nums[i][j] = count++;
}
// 从右到左
for (; j > starty; j--) {
nums[i][j] = count++;
}
// 从下到上
for (; i > startx; i--) {
nums[i][j] = count++;
}
startx++;
starty++;
offset++;
turns++;
}
// 如果是奇数个元素构成的矩阵,最后的中心位置需要单独处理
if (n % 2 == 1) {
// 最后的起始位置就是「矩阵的中心位置」
nums[startx][starty] = count;
}
return nums;
}
}