数组之滑动窗口法及模拟过程
209. 长度最小的子数组
此题可使用暴力解法,即先记录子数组开头位置并进行循环,再对于每个开头元素找到符合要求的最小子数组,并记录长度。
def minSubArrayLen(self, target: int, nums: List[int]) -> int:
left = 0
re = []
while left < len(nums):
add = nums[left]
right = left + 1
while add < target and right < len(nums):
add = add + nums[right]
right = right + 1
if add >= target:
re.append(right-left)
else:
re.append(0)
left = left + 1
if sum(re) == 0:
return 0
else:
return min([ele for ele in re if ele>0])
此暴力算法仍不够简洁,按题意只需要一个整数型变量re记录符合要求的子数组长度,无需开辟一个数组re。
但暴力解法的时间复杂度为O(n^2),会显示超时,可使用滑动窗口法使得时间复杂度降为O(n)
滑动窗口法可以理解为特殊的双指针法,两个指针分别指向子数组的开头和末尾。特别的是在滑动窗口法中,只对指向子数组末尾的指针进行循环,若窗口内的元素之和大于或等于目标值,则指向子数组开头的指针向前移动。
这种方法中指向开头的指针不会重复遍历数组,降低了时间复杂度。
def minSubArrayLen(self, target: int, nums: List[int]) -> int:
right = 0
left = 0
count = inf
add = 0
while right <= len(nums) - 1:
add = add + nums[right]
while add >= target:
if left == right:
return 1
else:
if count > right - left + 1:
count = right - left + 1
add = add - nums[left]
left = left + 1
right = right + 1
if count == inf:
return 0
else:
return count
59 . 螺旋矩阵Ⅱ
一开始对此题毫无思路,看了题解后发现是自己无法梳理清楚循环的条件以及不知道怎么对循环分层和分段。
此题中转一圈可视为一层,每一层的共同点是该层元素坐标中的不变量(横坐标或纵坐标)相同,且循环的元素和层数相关。在每一层中,根据不变量需要将其分为四段,此处的分法要保证每层分割的规则相同,可类比二分法中对循环条件的处理。
def generateMatrix(self, n: int) -> List[List[int]]:
num = 1
re = [[j for j in range(0,n)]for i in range(0,n)]
for round in range(0,n//2):
x = round
for y in range(round,n-1-round):
re[x][y] = num
num = num + 1
y = n-1-round
for x in range(round,n-1-round):
re[x][y] = num
num = num + 1
x = n-1-round
for y in reversed(range(round+1,n-round)):
re[x][y] = num
num = num + 1
y = round
for x in reversed(range(round+1,n-round)):
re[x][y] = num
num = num + 1
if n%2 == 1:
re[n//2][n//2] = n**2
return re
# 注意一共转n//2个round
# 每个for循环均为循环不变量
本文介绍了如何使用滑动窗口法解决LeetCode问题209(长度最小的子数组),降低时间复杂度至O(n)。同时,对LeetCode问题59(螺旋矩阵II)的解题思路进行了分析,强调了循环条件和分层处理的重要性。
835

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



