您现在的位置是:首页 >技术交流 >LeetCode刷题 | 977. 有序数组的平方、209. 长度最小的子数组、59. 螺旋矩阵 II网站首页技术交流
LeetCode刷题 | 977. 有序数组的平方、209. 长度最小的子数组、59. 螺旋矩阵 II
简介LeetCode刷题 | 977. 有序数组的平方、209. 长度最小的子数组、59. 螺旋矩阵 II
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;
}
}
双指针法
数组其实是有序的, 只不过负数平方之后可能成为最大数了。
那么数组平方的最大值就在数组的两端,不是最左边就是最右边,不可能是中间。
此时可以考虑双指针法了,i指向起始位置,j指向终止位置。
定义一个新数组result,和A数组一样的大小,让k指向result数组终止位置。
如果A[i] * A[i] < A[j] * A[j]
那么result[k--] = A[j] * A[j];
。
如果A[i] * A[i] >= A[j] * A[j]
那么result[k--] = A[i] * A[i];
。
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. 长度最小的子数组
暴力解法
两个for循环,然后不断的寻找符合条件的子序列,时间复杂度是O(n^2)。
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int result = Integer.MAX_VALUE;
int length = 0;
int sum = 0;
int k = 1;
for(int i = 0;i < nums.length;i ++){
sum = 0;
for(int j = i;j < nums.length;j ++){
sum += nums[j];
if(sum >= target){
length = j - i + 1;
result = result < length ? result : length;
break;
}
}
}
return result == Integer.MAX_VALUE ? 0 : result;
}
}
//代码最终超时了。。
滑动窗口
在本题中实现滑动窗口,主要确定如下三点:
- 窗口内是什么?
- 如何移动窗口的起始位置?
- 如何移动窗口的结束位置?
窗口就是 满足其和 ≥ s 的长度最小的 连续 子数组。
窗口的起始位置如何移动:如果当前窗口的值大于s了,窗口就要向前移动了(也就是该缩小了)。
窗口的结束位置如何移动:窗口的结束位置就是遍历数组的指针,也就是for循环里的索引。
解题的关键在于 窗口的起始位置如何移动,如图所示:
可以发现滑动窗口的精妙之处在于根据当前子序列和大小的情况,不断调节子序列的起始位置。从而将O(n^2)暴力解法降为O(n)。
class Solution {
public int minSubArrayLen(int target, 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 >= target){
result = Math.min(result,right - left + 1);
sum -= nums[left++];
}
}
return result == Integer.MAX_VALUE ? 0 : result;
}
}
59. 螺旋矩阵 II
不涉及算法,模拟顺时针画矩阵的过程:
- 填充上行从左到右
- 填充右列从上到下
- 填充下行从右到左
- 填充左列从下到上
由外向内一圈一圈这么画下去。
class Solution {
public int[][] generateMatrix(int n) {
int loop = 0;
int[][] res = new int[n][n];
int start = 0;
int count = 1;
int i,j;
while(loop++ < 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;
}
}
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。