977、有序数组的平方
最初我想到的为暴力解法 时间复杂度为 O(nlogn)
(直接遍历每一个数组元素使其平方,然后进行排序)
class Solution {
public int[] sortedSquares(int[] nums) {
int[] sq = new int[nums.length];
for(int i = 0;i<nums.length;i++){
sq[i] = nums[i] * nums[i];
}
Arrays.sort(sq);
return sq;
}
}
双指针解法 时间复杂度为 O(n)
接下来在视频提示下,指导可以使用双指针(由于是含负数的有序数组 =》由数组中间的元素朝两边的元素平方是依次增大的 =》 创建 left ,right 指针利用归并思想将其存入新的数组(用空间换时间))
class Solution {
public int[] sortedSquares(int[] nums) {
int n = nums.length;
int left = 0;
int right = n - 1;
int[] res = new int[n];
while(left <= right){
int Lsq = nums[left] * nums[left];
int Rsq = nums[right] * nums[right];
if(n > 0){
if(Lsq <= Rsq){
res[n - 1] = Rsq;
right--;
n--;
}else{
res[n - 1] = Lsq;
left++;
n--;
}
}
}
return res;
}
}
209、长度最小的子数组
看见 连续子数组 首先就想到了滑动窗口思想
自己根据理解的滑动窗口思想写了一个题解
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int left = 0;
int right = 0;
int res = Integer.MAX_VALUE;
int len = 0;
int sum = 0;
while(right < nums.length){
while(right < nums.length && sum < target){
sum += nums[right++];
len++;
}
System.out.println(sum);
if(right == nums.length && sum < target && res == Integer.MAX_VALUE){
return 0;
}
res = Math.min(len,res);
while(sum >= target){
res = Math.min(len,res);
sum -= nums[left++];
len--;
}
}
return res == Integer.MAX_VALUE ? 0 : res;
}
}
但是时间复杂度很高 O(n^2) 最坏的情况下需要遍历两次,有点重复冗杂
观察代码后发现:
在第二个while循环中,当子数组的总和已经大于等于目标值时,将左指针向右移动并更新子数组长度,然后再次判断总和是否大于等于目标值,这会导致在右指针不断向右移动的过程中,重复计算子数组的长度。
例:
例如,当nums数组为[2,3,1,2,4,3],target为7时,第一个子数组为[2,3,1,2],长度为4,当右指针移动到4时,子数组变为[4,3],长度变为2,但是在执行第二个while循环时,左指针向右移动,子数组变为[3],长度变为1,然后再次判断总和是否大于等于目标值,重复计算子数组的长度。
修改后:
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int left = 0;
int right = 0;
int sum = 0;
int res = Integer.MAX_VALUE;
int len = 0;
while (right < nums.length) {
sum += nums[right];
len++;
while (sum >= target) {
res = Math.min(res, len);
sum -= nums[left];
left++;
len--;
}
right++;
}
return res == Integer.MAX_VALUE ? 0 : res;
}
}
59、螺旋矩阵II
看见该题目时,第一想法就是模拟,大脑先跟着题目要求走,找到构成螺旋数组的一些限制条件代码便如下:
class Solution {
public int[][] generateMatrix(int n) {
int[][] matrix = new int[n][n]; // 创建一个 n × n 的矩阵
int num = 1; // 要填充的数字,初始值为 1
int rowStart = 0, rowEnd = n - 1; // 当前填充区域的上下边界
int colStart = 0, colEnd = n - 1; // 当前填充区域的左右边界
while (rowStart <= rowEnd && colStart <= colEnd) { // 当还有未填充的区域时继续循环
// 填充上行
for (int j = colStart; j <= colEnd; j++) {
matrix[rowStart][j] = num++; // 将当前数字填充到矩阵中,并将 num 加一
}
rowStart++; // 上边界下移一行
// 填充右列
for (int i = rowStart; i <= rowEnd; i++) {
matrix[i][colEnd] = num++; // 将当前数字填充到矩阵中,并将 num 加一
}
colEnd--; // 右边界左移一列
// 填充下行
if (rowStart <= rowEnd) { // 如果当前上下边界仍然有交叉区域
for (int j = colEnd; j >= colStart; j--) {
matrix[rowEnd][j] = num++; // 将当前数字填充到矩阵中,并将 num 加一
}
rowEnd--; // 下边界上移一行
}
// 填充左列
if (colStart <= colEnd) { // 如果当前左右边界仍然有交叉区域
for (int i = rowEnd; i >= rowStart; i--) {
matrix[i][colStart] = num++; // 将当前数字填充到矩阵中,并将 num 加一
}
colStart++; // 左边界右移一列
}
}
return matrix; // 返回填充好的矩阵
}
}
该题目解决后的思考:需要关注一些不变量来寻找规律,并利用它们来进行题目解决过程中的一些限制