LeetCodeCampsDay2
LeetCodeCamps—Day1
同样需要使用快/慢指针/双指针,另外,可以使用前缀和数组、二分查找
209. 长度最小的子数组
https://leetcode.cn/problems/minimum-size-subarray-sum/
问题
给定一个含有
n
个正整数的数组和一个正整数target
找出该数组中满足其总和大于等于
target
的长度最小的 子数组[numsl, numsl+1, ..., numsr-1, numsr]
,并返回其长度**。**如果不存在符合条件的子数组,返回0
。
示例 1:
1 | 输入:target = 7, nums = [2,3,1,2,4,3] |
示例 2:
1 | 输入:target = 4, nums = [1,4,4] |
示例 3:
1 | 输入:target = 11, nums = [1,1,1,1,1,1,1,1] |
提示:
1 <= target <= 109
1 <= nums.length <= 105
1 <= nums[i] <= 104
进阶:
- 如果你已经实现
O(n)
时间复杂度的解法, 请尝试设计一个O(n log(n))
时间复杂度的解法。
核心思路
- 外循环:使用for循环,被遍历对象为快指针(right),通过 right 指针扩展窗口
- 内循环:当窗口和(the sum of windows) >= target 时,记录当前窗口长度,并尝试收缩(shrink)窗口以找到更小的子数组
- 跳出条件:如果数组为空或没有符合的子数组,min_length 保持为最大值float(‘inf’)时,最终返回 0
代码
1 | class Solution: |
O(nlogn)时间复杂度的解法
这个解法使用前缀和数组
(prefix array)结合二分查找
:
先计算前缀和数组
,prefix[i] 表示 nums[0] 到 nums[i-1] 的和
对于每个右端点 j(对应子数组结束位置),使用二分查找找到第一个子数组和 >= target 的最大右端点。
时间复杂度:O(n log n),因为计算前缀和是 O(n),每个右端点进行一次二分查找是 O(log n),总共 O(n log n)
空间复杂度:O(n),用于存储前缀和数组
思路
- 使用前缀和数组来快速计算子数组的总和
- 我们需要找到一个子区间nums[j…k],而且sum(nums[j…k]) >= target;而sum(nums[j…k]) = prefix[k+1] - prefix[j],于是就有prefix[k+1] - prefix[j] >= target, 于是就有prefix[k+1] >= target + prefix[j]
- 使用(变体)二分搜索在前缀和数组中(从prefix[j…k]),找到第一个大于target + prefix[j]的下标mid,从而计算最小长度
代码
1 | L = len(nums) |
59. 螺旋矩阵 II
https://leetcode.cn/problems/spiral-matrix-ii/
给你一个正整数
n
,生成一个包含1
到n2
所有元素,且元素按顺时针顺序螺旋排列的n x n
正方形矩阵matrix
。
示例 1:
1 | 输入:n = 3 |
示例 2:
1 | 输入:n = 1 |
提示:
1 <= n <= 20
思路
这题目不考算法,但考编程能力;
这题目有个关键点是,弄清楚赋值的规律:将上、右、下、左四条边依次赋值,并且每次赋值时,都遵循“左开右闭”原则
比如第一行1->2->3,仅赋值1和2),而第二条(3->4->5),仅赋值(3->4);第三条(5->6->7),仅赋值(5->6);最后一条(7->8->1),同样仅赋值(7->8)
这样完成了一个“回”字形赋值
代码
下面代码可以优化成仅用一个offset,因为startX/startY与offset变化方式是一致的
1 | class Solution: |