LeetCode209 长度最小的子数组
题目链接:长度最小的子数组
暴力求解
本题的暴力求解思路很简单,由于是在一个完整的数组中寻找能够满足满足>=target的最小子数组,那么很容易就能想到使用两层for循环来遍历。外层for循环来遍历子数组的开始位置,内层for循环来遍历子数组的结束位置,当子数组之和满足条件(即>= target)时,即跳出内层循环。
通过这种两层for循环的方式,我们可以遍历所有的搜索空间。
class Solution:
def minSubArrayLen(self, target: int, nums: List[int]) -> int:
sLen = len(nums) + 1
# 暴力求解: 双重循环,遍历所有搜索空间 外层循环遍历区间的起始值,内层循环遍历区间的终止值 会超时
for i in range(len(nums)):
temp = 0
for j in range(i, len(nums)):
temp += nums[j]
if temp >= target: # 满足条件,即跳出内部循环,前移子数组的起始位置,即 i + 1
if j - i + 1 < sLen:
sLen = j - i + 1
continue
if sLen > len(nums):
return 0
else:
return sLen
但是使用暴力求解的方式,会导致程序运行超时,需要对程序进行优化,也就是引入下面的滑动窗口。
滑动窗口求解
首先需要思考的问题是:在使用滑动窗口时,需要对滑动窗口的开始位置进行遍历还是对结束位置进行遍历?我们思考一下,如果对开始位置进行遍历,那么此时和暴力求解好像没有什么区别,优化在哪里? 因此,我们需要对滑动窗口的结束位置进行遍历。
此外,当滑动窗口的右端前移之后,满足了大于等于target的条件,此时需要尝试迁移滑动窗口的左端,即滑动窗口的起始点。由于此时可能左端前移的此时大于1,因此此时需要使用while,而非if。
一个简单的例子:
若输入数组为:1,1,1,1,1,1,10,目标值targrt为11
那么此时在循环移动滑动窗口的结束点(右端)时,会直接移动到数组的末尾,此时尝试前移滑动窗口的左端,那么显然此时仅前移1次是不够的。
class Solution:
def minSubArrayLen(self, target: int, nums: List[int]) -> int:
total = len(nums)
sLen = total + 1
# 滑动窗口
i = 0
temp = 0
for j in range(total): # 遍历滑动窗口的结束位置
temp += nums[j] # 计算滑动窗口之和
while temp >= target: # 滑动窗口满足,尝试前滑动窗口起始点
if j - i + 1 < sLen:
sLen = j - i + 1
temp -= nums[i]
i += 1
if sLen > total:
return 0
else:
return sLen
LeetCode59 螺旋矩阵II
题目链接:螺旋矩阵II
本题并没有考验太多的算法,而是直接的控制数组。但是在实际写代码时,容易遇到的问题是:每次遍历边时,所采取的策略不一致,那么此时就会存在边界问题,导致一如循环深似海。
本题与Day1中的二分法一致,需要明确循环不变量,即在多次循环时需要保持一致的策略。这里在遍历每条边时,我们采用左闭右开,在处理每条边时,只处理该边起始点与结束点前的一个点,具体的示意图如下所示,十分清晰:

class Solution:
def generateMatrix(self, n: int) -> List[List[int]]:
startx = 0
starty = 0
offset = 1
num = 1
result = [[n*n]*n for _ in range(n)] # 构建默认值为n*n的二维数组
times = 1
i = 0
j = 0
while times <= n//2:
# 遍历一圈
i = startx
j = starty
# 遍历上层
while(j < n - offset):
result[i][j] = num
num += 1
j += 1
# 遍历右层
while(i < n - offset):
result[i][j] = num
num += 1
i += 1
# 遍历下层
while(j > starty):
result[i][j] = num
num += 1
j -= 1
# 遍历左层
while(i > startx):
result[i][j] = num
num += 1
i -= 1
# 一圈遍历完,移动到内圈
startx += 1
starty += 1
offset += 1
# 进行下一次循环
times += 1
return result
代码随想录 58.区间和
题目链接:区间和
本题需要确定一个数组内部指定两个索引的子区间内所有元素之和。
我们非常容易想到暴力遍历求解,但是会超时。
前缀和: 前缀和是数组问题中比较常用的解决策略,通过维护一个与输入数组等长的额外数组来存储前缀和,那么对于区间a,b之间所有元素的和就位对应前缀和相减。
#include <iostream>
#include <vector>
using namespace std;
int main(){
int n, a, b;
cin >> n;
vector<int> vec(n);
vector<int> p(n);
int presum = 0;
for(int i = 0; i < n; i++){
cin >> vec[i];
presum += vec[i];
p[i] = presum;
}
while(cin >> a >> b){
int sum;
if(a == 0) sum = p[b];
else sum = p[b] - p[a - 1];
cout << sum << endl;
}
}

885

被折叠的 条评论
为什么被折叠?



