滑动 window 算法 - 开始条件 < n
sliding window algorithm - condition for start < n
下面是一个滑动 window 解决方案,用于从 geeksforgeeks (https://www.geeksforgeeks.org/minimum-length-subarray-sum-greater-given-value/)
中找到总和大于 x 的最小长度子数组
# O(n) solution for finding smallest
# subarray with sum greater than x
# Returns length of smallest subarray
# with sum greater than x. If there
# is no subarray with given sum, then
# returns n + 1
def smallestSubWithSum(arr, n, x):
# Initialize current sum and minimum length
curr_sum = 0
min_len = n + 1
# Initialize starting and ending indexes
start = 0
end = 0
while (end < n):
# Keep adding array elements while current
# sum is smaller than x
while (curr_sum <= x and end < n):
curr_sum += arr[end]
end+= 1
# If current sum becomes greater than x.
while (curr_sum > x and start < n):
# Update minimum length if needed
if (end - start < min_len):
min_len = end - start
# remove starting elements
curr_sum -= arr[start]
start+= 1
return min_len
我已经测试过这个解决方案可以工作,但我很困惑为什么在最后一个 while 循环中检查 start 是否小于 n - 你不希望它小于 end,否则就开始可以超越终点,这对我来说真的没有意义吗?
由于 curr_sum 是通过将元素添加到 end 构建的,因此在 start 到达 end 之前它将变为零(或小于 x)。这将退出 while 循环。这也意味着该算法可能不适用于数组中的负数。
就我个人而言,我会写得有点不同。这是一个考虑了负数条件的例子:
def minSub(arr,x):
subTotal = 0
size,minSize = 0,len(arr)+1
start = iter(arr)
for value in arr:
subTotal += value
size += 1
while subTotal not in range(0,x+1):
if subTotal>x :
minSize = min(minSize,size)
subTotal -= next(start,0)
size -= 1
return minSize
输出:
arr = [1, 4, 45, 6, 0, 19]
x = 51
print(minSub(arr,x)) #3
arr = [-8, 1, 4, -1, 3, -6]
x = 6
print(minSub(arr,x)) # 4
arr = [1, 11, 100, 1, 0, 200, 3, 2, 1, 250]
x = 280
print(minSub(arr,x)) # 4
arr = [1, 10, 5, 2, 7]
x = 9
print(minSub(arr,x)) # 1
arr = [1, 2, 4]
x = 8
print(minSub(arr,x)) # 4
下面是一个滑动 window 解决方案,用于从 geeksforgeeks (https://www.geeksforgeeks.org/minimum-length-subarray-sum-greater-given-value/)
中找到总和大于 x 的最小长度子数组# O(n) solution for finding smallest
# subarray with sum greater than x
# Returns length of smallest subarray
# with sum greater than x. If there
# is no subarray with given sum, then
# returns n + 1
def smallestSubWithSum(arr, n, x):
# Initialize current sum and minimum length
curr_sum = 0
min_len = n + 1
# Initialize starting and ending indexes
start = 0
end = 0
while (end < n):
# Keep adding array elements while current
# sum is smaller than x
while (curr_sum <= x and end < n):
curr_sum += arr[end]
end+= 1
# If current sum becomes greater than x.
while (curr_sum > x and start < n):
# Update minimum length if needed
if (end - start < min_len):
min_len = end - start
# remove starting elements
curr_sum -= arr[start]
start+= 1
return min_len
我已经测试过这个解决方案可以工作,但我很困惑为什么在最后一个 while 循环中检查 start 是否小于 n - 你不希望它小于 end,否则就开始可以超越终点,这对我来说真的没有意义吗?
由于 curr_sum 是通过将元素添加到 end 构建的,因此在 start 到达 end 之前它将变为零(或小于 x)。这将退出 while 循环。这也意味着该算法可能不适用于数组中的负数。
就我个人而言,我会写得有点不同。这是一个考虑了负数条件的例子:
def minSub(arr,x):
subTotal = 0
size,minSize = 0,len(arr)+1
start = iter(arr)
for value in arr:
subTotal += value
size += 1
while subTotal not in range(0,x+1):
if subTotal>x :
minSize = min(minSize,size)
subTotal -= next(start,0)
size -= 1
return minSize
输出:
arr = [1, 4, 45, 6, 0, 19]
x = 51
print(minSub(arr,x)) #3
arr = [-8, 1, 4, -1, 3, -6]
x = 6
print(minSub(arr,x)) # 4
arr = [1, 11, 100, 1, 0, 200, 3, 2, 1, 250]
x = 280
print(minSub(arr,x)) # 4
arr = [1, 10, 5, 2, 7]
x = 9
print(minSub(arr,x)) # 1
arr = [1, 2, 4]
x = 8
print(minSub(arr,x)) # 4