977.有序数组的平方
题目建议: 本题关键在于理解双指针思想
题目链接:https://leetcode.cn/problems/squares-of-a-sorted-array/
文章讲解:https://programmercarl.com/0977.%E6%9C%89%E5%BA%8F%E6%95%B0%E7%BB%84%E7%9A%84%E5%B9%B3%E6%96%B9.html
视频讲解: https://www.bilibili.com/video/BV1QB4y1D7ep
思路想法:1)非递减排好的数组,则非负数部分直接返回数字平方值就为非递减顺序
2)负数部分,由于也是按非递减排列,则直接平方后为非递增顺序
3)需要考虑,将负数部分的平方插入到非负数平方返回后的数组中合适位置
然而写不出来.....
暴力:
第 1 步:一层 for 循环遍历数组,将各元素平方后存入数组,这一步的时间复杂度为 O(n)。
第 2 步:快排,时间复杂度为 O(nlogn)。
总的时间复杂度显然是 O(n + nlogn)
class Solution { public int[] sortedSquares(int[] nums) { for(int i= 0;i< nums.length;i ++){ nums[i] *=nums[i]; } Arrays.sort(nums); return nums; } }
双指针
思路:
数组其实是有序的, 只不过负数平方之后可能成为最大数了。
那么数组平方的最大值就在数组的两端,不是最左边就是最右边,不可能是中间。
此时可以考虑双指针法了,i指向起始位置,j指向终止位置。
定义一个新数组result,和A数组一样的大小,让k指向result数组终止位置。
看思路自己写,然后调试,code如下:
class Solution { public int[] sortedSquares(int[] nums) { int[] sortedNums = new int[nums.length]; int left = 0; int right = nums.length - 1; int index = nums.length - 1; while(left <= right){ if(nums[left] * nums[left] < nums[right] * nums[right]){ sortedNums[index] = nums[right] * nums[right]; right --; }else{ sortedNums[index] = nums[left] * nums[left]; left ++; } index --; } return sortedNums; } }
参考答案:
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; } }
学习简洁的代码
class Solution { public int[] sortedSquares(int[] nums) { int l = 0; int r = nums.length - 1; int[] res = new int[nums.length]; int j = nums.length - 1; while(l <= r){ if(nums[l] * nums[l] > nums[r] * nums[r]){ res[j--] = nums[l] * nums[l++]; }else{ res[j--] = nums[r] * nums[r--]; } } return res; } }
209.长度最小的子数组
题目建议: 本题关键在于理解滑动窗口
题目链接:https://leetcode.cn/problems/minimum-size-subarray-sum/
视频讲解:https://www.bilibili.com/video/BV1tZ4y1q7XE
思路想法:
滑动窗口,窗口值初始为1,逐渐递增,自左向右滑动,查看窗口内之和是否满足条件
class Solution { public int minSubArrayLen(int target, int[] nums) { int win = 1; while (win < nums.length + 1){ for(int l = 0;(l + win -1 ) < nums.length;l ++){ int r = l + win -1; int res = 0; while(l <= r){ res += nums[l++]; if(res >= target){ return win; } } } return 0; } }
超时
在本题中实现滑动窗口,主要确定如下三点:
- 窗口内是什么?
- 如何移动窗口的起始位置?
- 如何移动窗口的结束位置?
窗口就是 满足其和 ≥ s 的长度最小的 连续 子数组。
窗口的起始位置如何移动:如果当前窗口的值大于s了,窗口就要向前移动了(也就是该缩小了)。
窗口的结束位置如何移动:窗口的结束位置就是遍历数组的指针,也就是for循环里的索引。
class Solution { public int minSubArrayLen(int target, int[] nums) { int res = Integer.MAX_VALUE; int left = 0; int sum = 0; for(int right = 0;right < nums.length;right++){ sum += nums[right]; while(sum >= target){ res = Math.min(res,right - left + 1); sum -= nums[left++]; } } return res == Integer.MAX_VALUE ? 0 : res; } }
- 时间复杂度:O(n)
- 空间复杂度:O(1)
总结:知道大概思路,写不出来=。=
59.螺旋矩阵II
题目建议: 本题关键还是在转圈的逻辑,在二分搜索中提到的区间定义,在这里又用上了。
题目链接:https://leetcode.cn/problems/spiral-matrix-ii/
文章讲解:https://programmercarl.com/0059.%E8%9E%BA%E6%97%8B%E7%9F%A9%E9%98%B5II.html
视频讲解:https://www.bilibili.com/video/BV1SL4y1N7mV/
想法思路:
n行n列,自左向右:第一行为1到n;自上到下:第n列为n到2n-1(n+n-1); 自右向左:第n行为2n-1(n+n-1)到3n-2(n+n-1+n-1);自下到上:第一列为3n-2(n+n-1+n-1)到4n-4(n+n-1+n-1 + n-1-1)
不会
看答案:左闭右开、左闭右开、左闭右开!!!
转n/2圈,
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开始 // 模拟上侧从左到右 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; } }
先打个卡,2022年11月18日00:39:31,明天再研究
标签:977,right,nums,int,res,随想录,++,数组 From: https://www.cnblogs.com/gaoyuan2lty/p/16901911.html