代码随想录算法训练营第二天 | 977.有序数组的平方209.长度最小的子数组59.螺旋矩阵II
Posted 蔚尺丈八声
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了代码随想录算法训练营第二天 | 977.有序数组的平方209.长度最小的子数组59.螺旋矩阵II相关的知识,希望对你有一定的参考价值。
有序数组的平方
class Solution
public int[] sortedSquares(int[] nums)
/*
* 思路:双指针
*
* 参考: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
*
* 因为数组含有负数,若是负数的平方有可能大于正数的,所以构造两个指针i和j,
* 分别指向原数组nums[]的两端,再一个指针k指向所构造新数组result[]的末端,从后往前
* 依次存入nums[i]的平方和nums[j]的平方的比较结果,哪个大就先存入result[k],然后k
* 往前移动一格,nums[i]和nums[j]的平方中哪个大的就朝对向移动一格。
*
*/
int result[] = new int[nums.length];
int i = 0, j = nums.length - 1;
for (int k = nums.length - 1; k >= 0; k--)
int left_square = nums[i] * nums[i];
int right_square = nums[j] * nums[j];
if (left_square <= right_square)
result[k] = right_square;
j--;
else
result[k] = left_square;
i++;
return result;
public static void main(String[] args)
Solution solution1 = new Solution();
int nums[] = -7, -3, 2, 3, 11 ;
int result[] = solution1.sortedSquares(nums);
for (int c : result)
System.out.println(c);
长度最小的子数组
class Solution
public int minSubArrayLen(int target, int[] nums)
/*
* 思路:滑动窗口
*
* 参考:
* 【滑动窗口模板】https://www.bilibili.com/video/BV1V44y1s7zJ/?spm_id_from=333.1007.
* top_right_bar_window_history.content.click&vd_source=
* accc6a9ec558fa81b34f121125d4eff0
* 【动态规划】https://www.bilibili.com/video/BV16G411c7yZ/?spm_id_from=333.788.
* top_right_bar_window_custom_collection.content.click&vd_source=
* accc6a9ec558fa81b34f121125d4eff0
* 【贪心算法】https://blog.csdn.net/effective_coder/article/details/8736718
* 【滑动窗口解法】https://leetcode.cn/problems/minimum-size-subarray-sum/solutions/
* 306066/javade-jie-fa-ji-bai-liao-9985de-yong-hu-by-sdwwld/
* /javade-jie-fa-ji-bai-liao-9985de-yong-hu-by-sdwwld/
* 【官方题解】https://leetcode.cn/problems/minimum-size-subarray-sum/solutions/305704
* /chang-du-zui-xiao-de-zi-shu-zu-by-leetcode-solutio/
* 【前缀和】https://zhuanlan.zhihu.com/p/117569086#:~:text=%E5%89%8D%E7%BC%80%E5%92%
* 8C%E6%98%AF%E4%B8%80%E7%A7%8D%E9%A2%84%E5%A4%84%E7%90%86%EF%BC%8C%E7%94%A8%E4
* %BA%8E%E9%99%8D%E4%BD%8E%E6%9F%A5%E8%AF%A2%E6%97%B6%E7%9A%84%E6%97%B6%E9%97%
* B4%E5%A4%8D%E6%9D%82%E5%BA%A6%E3%80%82%20%E4%B8%BE%E4%B8%AA%E4%BE%8B%E5%AD%90
* %EF%BC%9A%E7%BB%99%E5%AE%9A%20n,%E4%B8%AA%E6%95%B4%E6%95%B0%EF%BC%8C%E7%84%B6
* %E5%90%8E%E8%BF%9B%E8%A1%8C%20m%20%E6%AC%A1%E8%AF%A2%E9%97%AE%EF%BC%8C%E6%AF%
* 8F%E6%AC%A1%E8%AF%A2%E9%97%AE%E6%B1%82%E4%B8%80%E4%B8%AA%E5%8C%BA%E9%97%B4%E5
* %86%85%E5%80%BC%E7%9A%84%E5%92%8C%E3%80%82
* 【Arrays.binarySearch 详解】https://blog.csdn.net/londa/article/details/119296502
*
* 滑动窗口算法题应用场景:
* 关键词:
* 满足XXX条件(计算结果,出现次数,同时包含)
* 连续区间
* 最长/最短
* 子串/子数组子序列
* 例如:长度最小的子数组
*
* 滑动窗使用思路(寻找最长)
* ————核心:左右双指针(L,R)在起始点,R向右逐位滑动循环
* ————每次滑动过程中
* 如果:窗内元素满足条件,R向右扩大窗口,并更新最优结果
* 如果:窗内元素不满足条件,L向右缩小窗口
* ————R到达结尾
*
* // 最长模板
* // 初始化left,right,result,bestResult
* while(右指针没有到结尾)
* 窗口扩大,加入right对应元素,更新当前result
* while(result不满足要求)
* 窗口缩小,移除left对应元素,left右移
*
* 更新最优结果bestResult
* right++
*
* 返回bestResult
*
* // 最短模板
* // 初始化left,right,result,bestResult
* while(右指针没有到结尾)
* 窗口扩大,加入right对应元素,更新当前result
* while(result满足要求)
* 更新最优结果bestResult // 对右指针不设限制,因为条件是result满足要求
* 窗口缩小,移除left对应元素,left右移
*
* right++
*
* 返回bestResult
*
* 对于本题的解法,可以套用最短模板:
* 我们把数组中的元素不停的入队,直到总和大于等于s为止,接着记录下队列中元素的个数,
* 然后再不停的出队,直到队列中元素的和小于s为止(如果不小于s,也要记录下队列中元素的个数,
* 这个个数其实就是不小于s的连续子数组长度,我们要记录最小的即可)。
* 接着再把数组中的元素添加到队列中…重复上面的操作,直到数组中的元素全部使用完为止。
*/
int left = 0, right = 0; // 定义滑动窗口的左右指针
int result = 0; // 记录滑动窗口的和
int min_result_len = Integer.MAX_VALUE; // 记录滑动窗口的最小长度
while (right < nums.length)
// 右指针移动,向窗口装入元素
result += nums[right];
right++;
// 右移指针直到满足条件为止,此时进入内循环,才开始移动左指针
while (result >= target)
// 更新最优结果bestResult
// 子序列长度=右指针-左指针(因为外层循环有个right++,所以不用加1了)
min_result_len = Math.min(min_result_len, right - left);
// 窗口缩小,移除left对应元素,left右移
result -= nums[left];
left++;
// 如果在nums数组中找不到满足>=target的最小子序列,那么就返回0
return min_result_len == Integer.MAX_VALUE ? 0 : min_result_len;
public static void main(String[] args)
Solution solution1 = new Solution();
int nums[] = 1,1,1,1,1,1,1,1 ;
int target = 11;
int result = solution1.minSubArrayLen(target, nums);
System.out.println(result);
螺旋矩阵II
class Solution
public int[][] generateMatrix(int n)
/*
*
* 思路:模拟元素按顺时针前进的过程即可,注意完成每一行、每一列时,相应缩小边界
*
* 参考:https://leetcode.cn/problems/spiral-matrix-ii/solutions/12594/spiral-matrix-ii-mo-ni-fa-she-ding-bian-jie-qing-x/
*
* 生成一个nxn空矩阵mat,随后模拟整个向内环绕的填入过程:
* 1、定义当前左右上下边界,r,t,b,初始值num=1,送代终止值tar
* 2、当num<=tar时,始终按照从左到右、从上到下、从右到左、从下到上填入顺序
* 循环,每次填入后:
* 2.1、执行num+=1:得到下一个需要填入的数字;
* 2.2、更新边界:例如从左到右填完后,上边界t+=1,相当于上边界向内缩1。
* 3、使用num<=tar而不是t<r||t<b作为迭代条件,是为了解决当n为奇数
* 时,矩阵中心数字无法在选代过程中被填充的问题。
* 4、最终返回mat即可。
*
*
*
*/
int left = 0, right = n - 1, top = 0, bottom = n - 1;
int nums[][] = new int[n][n]; // 待生成索引的矩阵
int count = 1; // 记录路线上的元素数
int x = 0, y = 0; // 表示路线最前面的那个点的坐标,x对应行,y对应列
nums[x][y] = count; // 记录第一个元素
//for循环中变量定义成x或y的细节:按照通常的思维,x代表行,y代表列
//这样,就可以很容易区分出来变化的量应该放在[][]的第一个还是第二个
//对于变量的边界怎么定义:
//从左向右填充:填充的列肯定在[left,right]区间
//从上向下填充:填充的行肯定在[top,bottom]区间
//从右向左填充:填充的列肯定在[right,left]区间
//从下向上填充:填充的行肯定在[bootom,top]区间
//通过上面的总结会发现边界的起始和结束与方向是对应的
while (count < n * n)
// 先从左向右走
while (y < right)
y++;
count++;
nums[x][y] = count;
top++; // 缩小上边界
// 再从上向下走
while (x < bottom)
x++;
count++;
nums[x][y] = count;
right--; // 缩小右边界
// 再从右向左走
while (y > left)
y--;
count++;
nums[x][y] = count;
bottom--; // 缩小下边界
// 再从下向上走
while (x > top)
x--;
count++;
nums[x][y] = count;
left++; // 缩小左边界
return nums;
public static void main(String[] args)
Solution solution1 = new Solution();
int nums[][] = solution1.generateMatrix(3);
for (int c[] : nums)
for (int x : c)
System.out.println(x);
以上是关于代码随想录算法训练营第二天 | 977.有序数组的平方209.长度最小的子数组59.螺旋矩阵II的主要内容,如果未能解决你的问题,请参考以下文章
代码随想录算法训练营第五十二天 | 300.最长递增子序列 674. 最长连续递增序列 718. 最长重复子数组
代码随想录算法训练营第四十二天 | 01背包问题,你该了解这些01背包问题,你该了解这些 滚动数组 416. 分割等和子集
代码随想录算法训练营第六天 | 242.有效的字母异位词349. 两个数组的交集202. 快乐数1. 两数之和
代码随想录算法训练营第六天 | 242.有效的字母异位词349. 两个数组的交集202. 快乐数1. 两数之和