977 有序数组的平方
题目:力扣
第一反应:
先把每个数组的平方数计算出来,再进行排序
class Solution {
public int[] sortedSquares(int[] nums) {
for(int i=0; i<nums.length; i++){
nums[i] = nums[i]*nums[i];
}
Arrays.sort(nums);
return nums;
}
}
但是这样的时间复杂度是O(nlogn),不是最优的。
数组本身就是有序的,数组的平方可能会使原来为负数的元素变为最大的。最大的数一定是在两头之中产生,然后往中间移动。
--> 可以考虑双指针法。指向数组的头端和尾端。
创建一个新的数组,从最后开始填入,每次比较头尾的平方大小,将更大的填入并往中间移动。
class Solution {
public int[] sortedSquares(int[] nums) {
int left = 0;
int right = nums.length-1;
int[] result = new int[nums.length];
for(int i=nums.length -1; i>=0; i--){
if(nums[left]*nums[left] >= nums[right]*nums[right]){
result[i] = nums[left]*nums[left];
left++;
}else{
result[i] = nums[right]*nums[right];
right --;
}
}
return result;
}
}
参考资料:代码随想录
209.长度最少的子数组
题目:力扣
使用滑动窗口的思路
窗口就是 满足其和 ≥ s 的长度最小的 连续 子数组。
窗口的起始位置如何移动:如果当前窗口的值大于s了,窗口就要向前移动了(也就是该缩小了)。
窗口的结束位置如何移动:窗口的结束位置就是遍历数组的指针,也就是for循环里的索引。
编写代码时存在的bug:
使用while循环实现滑动窗口 - 一直在循环中
解决办法:使用for循环 - 针对右指针;while - 针对左指针
public int minSubArrayLen(int target, int[] nums) {
int left = 0;
int minL = nums.length+1;
int value = 0;
for(int right = 0; right<nums.length; right++){
value += nums[right];
while(value >= target){
minL = Math.min(minL, right - left +1);
value -= nums[left];
left++;
}
}
if(minL == nums.length+1){
return 0;
}
return minL;
}
参考资料:代码随想录
59. 螺旋矩阵
模拟法
难点:如何处理边界问题
两种思路:每次一边填入相同的数,左闭右开;每一次把一行或者一列填满,左闭右闭
实现的是第二种,感觉第一种在计算边界上比较麻烦一些
public int[][] generateMatrix(int n) {
int[][] result = new int[n][n];
int insert = 1; //填入表格中的数字
//设定边界
int left = 0;
int top = 0;
int right = n-1;
int bottom = n-1;
//模拟 - 注意左闭右闭
while(insert <= n*n){
//从左到右
for(int i = left; i<=right; i++){
result[top][i] = insert;
insert++;
}
top++;
//从上到下
for(int i= top; i<=bottom; i++){
result[i][right] = insert;
insert++;
}
right--;
//从右往左
for(int i=right; i>=left; i--){
result[bottom][i] = insert;
insert++;
}
bottom--;
//从下到上
for(int i= bottom; i>=top; i--){
result[i][left] = insert;
insert++;
}
left++;
}
return result;
}
参考资料:
类似题:
54.旋转矩阵
类似方法解题 - 注意是n*m的矩阵,注意边界问题
public List<Integer> spiralOrder(int[][] matrix) {
int n = matrix.length;
int m = matrix[0].length;
int left = 0;
int top = 0;
int right = m -1;
int bottom = n -1;
List<Integer> result = new ArrayList<>();
int count = 0;
while(count < n*m){
for(int i=left; i<=right; i++){
result.add(matrix[top][i]);//最上面一条
count++;
}
top++;
if(count == n*m) break;
for(int i=top; i<=bottom; i++){
result.add(matrix[i][right]);//最右边一条
count++;
}
right--;
if(count == n*m) break;
for(int i=right; i>=left; i--){
result.add(matrix[bottom][i]);//最下面一条
count++;
}
bottom--;
if(count == n*m) break;
for(int i=bottom; i>=top; i--){
result.add(matrix[i][left]);//最左边一条
count++;
}
left++;
}
return result;
}
数组题目总结:
常用的四个方法:
二分法、双指针法、滑动窗口法、模拟法
参考资料:代码随想录