分治法减治法的应用:现有一正整数数组A[N],一正常数K,要求从A中寻找一段连续子数组,使得该子数组的和不小于K,同时使得子数组的长度最小。如果存在满足条件的子数组,输出子数组两端在A中从1开始的序号;若不存在,则输出-1,-1。(提示:充分利用数组内元素都是正数这一特点。)
时间: 2025-07-09 14:42:11 浏览: 10
<think>嗯,这个问题看起来是要在一个正整数数组里找一段连续的子数组,使得子数组的和不小于给定的K,并且长度要最小。然后输出两端的位置,如果没有的话就输出-1,-1。首先,我得仔细理解题目要求。
首先,数组里的元素都是正整数,这个条件很重要。因为都是正数,所以子数组的和会随着长度的增加而单调递增。那这样的话,可能可以用滑动窗口的方法来解决,因为一旦窗口内的和达到K,就可以尝试缩小窗口的左边界,看看能不能找到更小的长度。这可能比暴力法更高效,暴力法是O(n²),而滑动窗口可以做到O(n)。不过题目提示里提到分治法或者减治法,可能需要考虑其他方法?
不过先想滑动窗口的思路。因为数组元素都是正数,所以当右指针右移时,和会增加,而当和超过K时,左指针可以右移来尝试缩小窗口。这样可能找到最小的长度。比如,初始时左右指针都在0的位置,然后右指针不断右移,直到和>=K,记录此时的长度。然后左指针右移一位,同时减去左边的值,再次检查是否和仍然>=K,如果是的话,继续右移左指针,直到和小于K,然后右指针再继续右移。这样每次记录满足条件时的最小长度。这种方法时间复杂度是O(n),应该不错。
比如举个例子,数组是[2,3,1,2,4,3],K=7。那么滑动窗口的过程可能如下:
初始sum=0,left=0,right=0。sum=2,不够。右移到3,sum=5,还是不够。右移到1,sum=6,不够。右移到2,sum=8>=7,此时长度是4-0+1?或者索引的问题要注意。这里可能需要确认数组的索引是从1开始还是0开始,题目要求输出两端在A中从1开始的序号,所以应该假设数组的索引是1-based。例如,数组A[1], A[2],...,A[N]。
那假设数组索引是1-based的情况下,当窗口是A[1]到A[4]时,和为2+3+1+2=8>=7,此时长度是4。然后左指针右移,sum减2,得到6,不够,所以右指针继续右移,到4的位置,sum=6+4=10>=7,此时窗口是A[2]到A[5],长度是4。继续左指针右移,sum减3,得到7,还是满足,此时长度是4-1=4?或者具体要看窗口的左右边界差。这时候左指针移动到3的位置,sum=1+2+4=7>=7,此时窗口长度是3(3到5),长度更小。然后继续左移,sum减1,得到6,不够,右指针右移,到6的位置,sum=6+3=9>=7,此时窗口是3到6,长度4。这样比较下来,最小长度是3,对应的位置是3到5,或者可能还有更小的?
或者这个例子可能有更优解,比如子数组[4,3]和为7,长度2,起始位置5和6。那可能我刚才的滑动窗口没有考虑到这种情况。这说明可能滑动窗口的方法需要调整,或者我的思路有问题。
哦,这里的问题可能在于,当窗口的和超过K时,应该尽可能移动左指针,尽可能缩小窗口的长度。例如,当右指针到达某个位置时,左指针可能需要多次移动,直到无法再移动为止,这样每次右指针移动后,都尽可能缩小左指针的位置,从而记录当前右指针位置下的最小窗口长度。
例如,在刚才的例子中,当右指针到达第5个元素(4)时,此时窗口是A[2]到A[5],和为3+1+2+4=10>=7。这时,左指针可以移动到3的位置,此时和为1+2+4=7,刚好满足,长度是3。之后右指针到第6个元素(3),和为7+3=10>=7。此时左指针可以继续移动到4的位置,sum=2+4+3=9>=7,长度3;然后左指针再移动到5的位置,sum=4+3=7>=7,长度2。这时候得到的长度是2,对应的位置是5和6。这说明滑动窗口需要更仔细地处理每次右指针移动后,尽可能移动左指针到最远的位置,这样就能找到更小的窗口。
这说明滑动窗口方法确实可行,但需要正确实现。那可能这个问题的最优解是滑动窗口法,时间复杂度为O(n),而分治或减治法可能是否适用?
那题目提示中提到分治法或减治法,可能需要考虑其他方法。但分治法可能的时间复杂度是O(n log n),比如类似求解最大子数组和的问题中的分治法。不过在这种情况下,滑动窗口已经可以达到O(n),可能更优。但题目要求用分治或者减治的话,可能需要另外的方法。
不过,可能用户的问题只是需要找到解决方案,而不一定严格按照分治或减治法。那可能给出滑动窗口的解法更实际,并且题目中的提示可能只是提示,不一定必须使用分治或减治。比如,可能问题的提示是让利用数组元素都是正数的特点,而滑动窗口正是利用这个特点的有效方法。
那接下来要思考如何正确实现滑动窗口法。步骤如下:
初始化左指针left=0(假设数组是0-based),当前和sum=0,最小长度min_len设为无穷大,结果的起始和结束索引为-1,-1。
遍历数组,右指针从0开始,逐步右移。每次将当前元素加到sum中。然后,当sum >= K时,尝试移动左指针尽可能多的位置,同时保持sum >= K。每次移动左指针时,减去对应的元素。每次满足sum >= K时,计算当前窗口的长度(right - left + 1),并比较是否更小,更新min_len以及结果的起始和结束索引。
需要注意的是,数组的索引是从1开始的,所以在存储结果的时候需要将left和right转换为1-based的索引。
例如,当left是0-based的索引i,right是j的话,对应的起始位置是i+1,结束位置是j+1。
举个例子,数组A = [2,3,1,2,4,3], K=7:
初始化left=0, sum=0, min_len=inf,result=(-1,-1)
右指针依次移动到各个位置:
右指针0(元素2),sum=2 <7 → 继续。
右指针1(元素3),sum=5 <7 → 继续。
右指针2(元素1),sum=6 <7 → 继续。
右指针3(元素2),sum=8 >=7。此时进入内部循环,移动左指针:
sum >=7,当前窗口长度是3-0 +1=4。记录min_len=4,结果(1,4)。然后减去A[left]=2,sum=6,left=1。此时sum=6 <7 → 停止移动左指针。
右指针4(元素4),sum=6+4=10 >=7。进入内部循环:
sum=10 >=7,此时窗口是1到4,长度4-1+1=4,当前min_len是4,还是4,所以不更新。尝试移动左指针:
减去A[1]=3 → sum=7 >=7。窗口长度4-2+1=3,所以min_len=3,结果(3,5)(因为left现在是2,对应3,right是4,对应5)。继续移动左指针:
减去A[2]=1 → sum=6 <7 → 停止。left=3.
此时sum=6+4=10?
或者可能我在这里的步骤有错误。可能我应该更仔细地重新计算:
当右指针移动到4(索引4,元素4)时,sum此时是之前的sum=6(left=1到3的和是3+1+2=6,对吗?或者可能我之前的步骤有错误?
或者,可能我的初始流程描述有问题。让我再仔细理一遍:
在滑动窗口的正确实现中,每次右指针移动一位,将当前元素加到sum中。然后,只要sum >= K,就尝试尽可能左移left,同时sum减去A[left],直到sum < K。每次移动left之前,都要检查当前窗口是否满足条件,并记录最小长度。
比如,当right=3(元素2)时,sum=2+3+1+2=8 >=7。此时进入内部循环:
此时窗口是0到3(即元素1到4的索引,转换为1-based则是1到4),长度4。记录min_len=4,结果1-4。然后,sum减去A[left]=A[0]=2 → sum=6,left=1。此时sum=6 <7,退出循环。此时right指针继续移动到4,sum +=4 → sum=6+4=10 >=7。进入内部循环:
此时sum=10 >=7,窗口是left=1到right=4(元素2到5的索引1-based)。长度是4-1+1=4。当前min_len是4,所以是否更小?是的,因为之前是4,现在也是4,所以无需更新。然后尝试移动left:
sum减去A[1]=3 → sum=7 >=7。此时left=2,窗口是2到4(元素3到5),长度3。此时记录min_len=3,结果3-5。继续尝试移动left:
sum减去A[2]=1 → sum=6 <7 → 退出循环。此时sum=6,left=3。然后right移动到5,sum +=3 → sum=9 >=7。进入循环:
此时窗口是3到5(元素4到6?或者索引的问题需要再次确认。原数组是0-based的right=5对应元素3,所以此时窗口是left=3到right=5(元素4,3)。sum=6+3=9 >=7。现在需要移动left:
当前窗口长度5-3+1=3。比较当前min_len是3,所以不更新。尝试移动left:
sum减去A[3]=2 → sum=7 >=7 → left=4,窗口长度5-4+1=2。此时min_len更新为2,结果5-6(因为left=4对应1-based的5,right=5对应6)。继续移动left:
sum减去A[4]=4 → sum=3 <7 → 退出循环。此时sum=3,left=5。此时right=5,无法再移动。
这样,最终得到的最小长度是2,对应位置5和6。所以结果应为5,6。
这说明滑动窗口的正确实现可以找到最优解。因此,正确的解法应该是滑动窗口,时间复杂度O(n),空间O(1)。
但题目中的提示提到了分治或减治法,可能用户希望得到这样的解法?或者可能用户只是需要正确的解法,不管方法类型?
但根据问题描述,用户的问题明确提到“分治法减治法的应用”,所以可能需要给出分治法或者减治法的思路。但这时候可能需要思考,如何用分治法解决这个问题。
分治法一般将问题分成几个子问题,然后合并结果。例如,在最大子数组和的问题中,分治法的思路是将数组分成左右两部分,然后最大子数组和可能出现在左半部分、右半部分,或者跨越中间点。然后递归求解,合并结果。
但是当前的问题是要找长度最小的子数组,其和>=K。是否可以用分治法?
假设将数组分成左右两半,那么最小的子数组可能在左半部分、右半部分,或者跨越中间的部分。合并的时候需要考虑这三者中的最小值。
对于跨越中间的部分,我们需要找到以中间为起点向左右扩展的子数组。但如何高效地找到这样的子数组?
例如,中间位置是mid。需要找到左边的某个位置i到右边的某个位置j,使得i在左半部分,j在右半部分,并且sum(A[i..j])>=K,同时长度j-i+1尽可能小。
但是由于数组元素都是正数,当计算中间区域的子数组时,可以尝试从中间向左找,使得sum尽可能大,同时尽可能短的左边,而右边同理。然后组合左右的可能解。
但这样的方法可能比较复杂,而且合并步骤的时间复杂度可能为O(n),因此总的时间复杂度是O(n log n),这比滑动窗口的O(n)要差。所以在这种情况下,滑动窗口法更优。
可能题目中的提示是引导用户想到滑动窗口法,而用户提到的分治或减治可能是一个误导,或者需要进一步澄清。
不过,根据用户的问题,题目明确要求“分治法减治法的应用”,所以可能需要给出分治法的解法。或者,可能用户的问题中的提示只是提示,而实际解法可以是其他方法。此时需要仔细看问题描述。
原问题的提示说:“提示:充分利用数组内元素都是正数这一特点。” 这可能暗示使用滑动窗口,因为正数的特性允许窗口的和单调增加,因此滑动窗口有效。而分治法可能并不直接利用这一特点,除非在合并步骤中使用这个特性。
综上,可能正确的解法是滑动窗口法,而分治法可能不是最优解。所以可能需要解释滑动窗口法,同时说明这是最优解法,而分治法可能较慢。
但根据用户的问题,可能需要给出分治法的应用。那么需要思考如何用分治法解决这个问题。
分治法的大致步骤:
1. 分解:将数组分成左右两半。
2. 解决:递归求解左半部分和右半部分的最小长度子数组。
3. 合并:考虑跨越中间点的子数组是否存在更小的解。
在合并步骤中,需要找到跨越中间点的子数组,其和>=K,并且长度尽可能小。如何高效地找到这样的子数组?
由于数组元素都是正数,当寻找跨越中间的子数组时,可以从中间点向左扩展,计算到中间点的各个左端点的前缀和,然后同样从中间点+1向右扩展,计算到中间点的各个右端点的后缀和。然后,对于每个左端点i(在左半部分),寻找最小的右端点j(在右半部分),使得sum(A[i..mid] + A[mid+1..j]) >= K。由于所有元素都是正数,sum随着j的增加而递增,因此对于每个i,可以找到最小的j,使得总和>=K,这样对应的窗口长度是j -i +1。然后在这些窗口中找到最小的长度。
例如,假设中间点是m。左半部分是A[1..m],右半是A[m+1..n]。对于跨越中间的解,需要找到i <=m,j >=m+1,使得sum(A[i..j]) >=K,并且j-i+1最小。
为了高效计算,可以预先计算左半部分的前缀和数组,从m到左边每个i的和,例如left_sums[i] = sum(A[i..m])。同理,计算右半部分的后缀和数组,right_sums[j] = sum(A[m+1..j])。
因为元素都是正数,left_sums是随着i的减小而增加的(因为i更小,覆盖更多的左边元素)。同理,right_sums是随着j的增大而增加的。
对于每个i从m downto 1,我们计算left_sums[i],然后我们需要找到一个最小的j >=m+1,使得left_sums[i] + right_sums[j] >= K。由于right_sums是递增的,可以使用二分查找来找到最小的j。
例如,对于每个i,计算需要的最小right_sum = K - left_sums[i]。如果这个值 <=0,那么只需要j=m+1即可,因为right_sums的最小值是A[m+1] >=0,但由于left_sums[i] >= K的话,那么此时j可以取m+1,但需要确保总和>=K。或者可能i到m的和已经>=K,这时候j可以是m,这样窗口是i到m,这属于左半部分,可能已经被递归处理了?
这里可能需要更仔细的分析。
假设我们处理跨越中间的情况,那么对于每个i在左半部分,我们计算sum_left = sum(A[i..m])。然后需要找到最小的j在右半部分,使得sum_left + sum(A[m+1..j]) >= K。因为sum(A[m+1..j])是递增的(元素都是正数),所以对于每个i,可以计算所需的最小sum_right >= (K - sum_left)。然后使用二分查找在右半部分的prefix sum数组中找到最小的j,使得sum_right >= (K - sum_left)。一旦找到这样的j,那么窗口长度是 (m -i +1) + (j - (m+1) +1 )= j -i +1.
例如,假设右半部分的prefix sums是从m+1到j的和,可以预先计算一个数组right_prefix,其中right_prefix[k] = sum(A[m+1..k])。然后对于每个i,我们需要的sum_right >= (K - sum_left_i),那么找到最小的k >=m+1,使得 right_prefix[k] >= (K - sum_left_i)。此时窗口是i到k,长度为k -i +1.
然后,对于所有i,我们找到对应的k,计算窗口长度,取最小的那个。
同样,反过来,可以预先计算左半部分的前缀和数组和右半部分的前缀和数组,然后对每个i在左半部分,进行二分查找。这样合并步骤的时间复杂度是O(n log n),而分治的总时间复杂度为O(n log n),因为每层是O(n log n),总共有O(log n)层,所以总时间复杂度是O(n (log n)^2)。或者可能合并步骤是O(n)的时间,因为对于每个i,二分查找是O(log n)时间,而i的数量是O(n),所以总的是O(n log n),导致分治法的时间复杂度为O(n log n) * log n)= O(n (log n)^2)。这可能比滑动窗口的O(n)差。
因此,分治法可能不是最优解,而滑动窗口更优。因此,正确的方法是滑动窗口法,而题目中的提示可能只是要利用正数特性,而不是必须用分治或减治。
综上,正确的解法应该是滑动窗口法,时间复杂度O(n),空间O(1)。那接下来需要给出具体的步骤和代码实现。
具体步骤:
1. 初始化左指针left=0,当前和sum=0,最小长度min_length设为无穷大,结果result=(-1,-1)。
2. 遍历右指针从0到n-1:
a. 将A[right]加到sum中。
b. 当sum >= K时,进入内部循环,尝试左移left以缩小窗口:
i. 记录当前窗口的长度right-left+1,如果比min_length小,则更新min_length和result为(left+1, right+1)(因为数组是1-based)。
ii. 减去A[left]的值,并将left右移一位。
iii. 重复直到sum < K。
3. 遍历结束后,如果min_length仍然是无穷大,则返回(-1,-1),否则返回result。
需要注意的是,当sum >=K时,可能存在多个左指针的位置,因此在每次右指针移动后,需要尽可能移动左指针到最远的位置,以保证找到最小的窗口。
例如,当右指针移动后sum >=K,此时不断将左指针右移,直到sum <K。每次移动左指针前,检查当前窗口是否满足条件,并更新min_length。
但这样可能会漏掉某些情况吗?比如,当左指针移动时,可能中间有多个满足条件的窗口,每次都要检查。
例如,当sum >=K时,每次左指针右移前,都计算当前窗口的长度,并比较是否更小。
举个例子,当sum >=K时,窗口是left到right,此时长度为right-left+1。然后左指针右移一位,sum减去A[left],left变为left+1,此时sum可能仍然>=K,因此需要继续检查,直到sum <K。
所以,在内部循环中,每次sum >=K时,计算当前窗口的长度,并尝试更新min_length,然后移动左指针。
这样的过程可以保证每次找到以当前right为结尾的最短满足条件的窗口,从而整体得到最短的窗口。
现在,需要验证这个算法是否能正确找到所有可能的解。
比如,之前的例子中,当right=5(元素3)时,sum=9,left=3。此时窗口是3到5(0-based),对应1-based是4到6。sum=9 >=7。此时进入循环:
计算窗口长度3(5-3+1=3)。如果此时的min_length之前是2(比如在更早的步骤中得到的),可能不会更新。否则,假设之前没有更小的,此时会更新min_length为3。然后减去A[3]=2,sum=7 >=7。left右移到4。此时窗口长度是5-4+1=2。这更小,所以更新min_length为2,result为5和6(4+1和5+1)。然后sum=7,再次进入循环,减去A[4]=4,sum=3 <7,退出循环。
这说明算法能正确找到最小窗口。
因此,正确的实现步骤如上所述。
现在,针对这个算法,编写伪代码或者具体步骤:
初始化left=0, sum=0, min_len=inf, result=(-1,-1)
for right in 0..n-1:
sum += A[right]
while sum >= K:
current_length = right - left +1
if current_length < min_len:
min_len = current_length
result = (left+1, right+1)
sum -= A[left]
left +=1
循环结束后,如果min_len仍是inf,返回-1,-1,否则返回result.
但是,这个时候需要注意,当sum >=K时,可能移动左指针多次,每次移动后都可能得到一个更小的窗口。例如,当right固定时,left不断右移,直到sum <K。每次移动前,都检查当前的窗口是否有效,并记录可能的更优解。
但这里有一个疑问:当右指针移动到一个位置,导致sum >=K,此时左指针移动,可能得到更小的窗口长度。但是,在移动左指针的过程中,可能之前已经存在更小的窗口长度。例如,当右指针到达某个位置后,可能左指针移动到某个位置,得到一个更短的窗口,但该窗口的右边界可能比之前的更短窗口的右边界更靠右,从而导致更小的长度。
例如,假设数组是[1,2,3,4,5], K=10。当右指针到3(元素4)时,sum=1+2+3+4=10 >=10,此时窗口长度4。然后左指针移动到1,sum=2+3+4=9 <10。此时,右指针继续移动到4(元素5),sum=9+5=14 >=10。此时窗口长度是4(从1到4,长度4)。然后左指针移动到2,sum=3+4+5=12 >=10,窗口长度3。再移动到3,sum=4+5=9 <10。此时记录的长度是3。而正确的最优解应该是子数组[4,5,1]?或者原数组是[1,2,3,4,5],K=10,最优解是[1,2,3,4](长度4)或 [2,3,4,5](sum 14,长度4)或者 [5,4](sum 9,不够)。哦,原例子中数组元素都是正数,所以该例中最优解应该是[4,5],和为9+5=14?或者原数组的元素是1,2,3,4,5,所以总和为15,而需要sum >=10。最短的窗口应该是[5,4],也就是长度2?或者原数组中[4,5]的和是9,不够。哦,原例子中的数组元素总和可能不够,或者我可能举了一个错误的例子。
假设数组是[1,2,3,4,5], K=10。那么正确的最小长度子数组是[4,5,1]?但数组是连续的,所以实际只能是连续的子数组。例如,正确的解是[2,3,4,5](sum 14,长度4),或者 [3,4,5](sum 12,长度3),或者 [5,4]?哦,抱歉,数组元素是连续的,所以[5]的和是5不够,[4,5]是9不够,[3,4,5]是12,长度3。或者原例子中的数组可能不够大。可能我需要另一个例子。
比如数组是[1,2,3,4,5], K=12。则正确解是[3,4,5],和为12,长度3。滑动窗口的执行步骤:
left=0, sum=0, right依次到各个位置:
right=0,sum=1 <12.
right=1,sum=3 <12.
right=2,sum=6 <12.
right=3,sum=10 <12.
right=4,sum=15 >=12. 进入循环:
current_length=4-0+1=5. 如果min_len是inf,更新为5,result=(1,5).
sum -=1 → sum=14. left=1.
此时sum >=12,current_length=4-1+1=4 → 更新min_len=4,result=(2,5).
sum -=2 → sum=12. left=2. current_length=3 → 更新min_len=3,result=(3,5).
sum -=3 → sum=9 <12. 退出循环.
此时min_len是3,结果正确。
这说明算法正确。
综上,滑动窗口算法是正确的。
因此,正确的解法是滑动窗口法,时间复杂度O(n),空间O(1)。
现在,回到问题要求,用户希望得到分治或减治法的应用,但实际最优解是滑动窗口。因此,可能需要说明两种方法,但重点在滑动窗口。
但问题中的提示可能希望引导用户想到滑动窗口,因为利用了正数的特性。所以最终回答应该以滑动窗口法为主,并说明其正确性和复杂度,可能不需要分治法,因为分治法的时间复杂度更高。
所以,在回答用户的问题时,应当介绍滑动窗口法,并说明如何实现,同时解释为什么它利用了数组元素都是正数的特性,从而高效地找到解。</think>### 问题分析
我们需要在一个正整数数组 `A[N]` 中找到一个**连续子数组**,使得子数组的和不小于给定常数 `K`,且子数组的长度最小。若存在多个解,输出任意一个满足条件的子数组的起始和结束序号(1-based);若不存在,则输出 `(-1, -1)`。
---
### 关键思路:滑动窗口法(双指针法)
**利用数组元素全为正数的性质**:
由于所有元素均为正数,当子数组的和增加到某一阈值时,继续扩展子数组的长度会导致和单调递增。因此,可以用滑动窗口动态调整左右边界,高效寻找最短满足条件的子数组。
**算法步骤**:
1. **初始化**:左指针 `left = 0`,当前和 `sum = 0`,最小长度 `min_len = +∞`,结果 `(-1, -1)`。
2. **遍历右指针**:将右指针 `right` 从 `0` 逐步移动到 `N-1`,每次将 `A[right]` 加入 `sum`。
3. **收缩左边界**:若 `sum ≥ K`,尝试右移左指针 `left` 以缩小窗口长度:
- 计算当前窗口长度 `right - left + 1`,若更小则更新结果。
- 从 `sum` 中减去 `A[left]`,并右移 `left`,直到 `sum < K`。
4. **返回结果**:若 `min_len` 未被更新,返回 `(-1, -1)`,否则返回记录的起始和结束序号。
---
### 正确性证明
1. **单调性**:由于元素全为正数,当右指针右移时,和必然增加;左指针右移时,和必然减少。
2. **最小长度保证**:每次右指针移动后,尽可能收缩左边界,确保以当前右指针为终点的最短窗口被记录。
---
### 复杂度分析
- **时间复杂度**:`O(N)`,左右指针各遍历数组一次。
- **空间复杂度**:`O(1)`,仅需常数空间存储指针和变量。
---
### 示例演示
**输入**:`A = [2, 3, 1, 2, 4, 3]`,`K = 7`
**执行步骤**:
1. `right=3` 时,`sum=8`,窗口为 `[2,3,1,2]`,长度 `4`。
2. 收缩左边界至 `left=2`,窗口变为 `[1,2,4]`,和 `7`,长度 `3`。
3. `right=5` 时,`sum=10`,最终收缩至 `left=4`,窗口为 `[4,3]`,和 `7`,长度 `2`。
**输出**:`(5, 6)`。
---
### 代码实现
```python
def find_min_subarray(A, K):
n = len(A)
left = 0
current_sum = 0
min_length = float('inf')
result = (-1, -1)
for right in range(n):
current_sum += A[right]
while current_sum >= K:
current_length = right - left + 1
if current_length < min_length:
min_length = current_length
result = (left + 1, right + 1) # 转换为1-based序号
current_sum -= A[left]
left += 1
return result if min_length != float('inf') else (-1, -1)
```
---
### 分治法(补充说明)
虽然滑动窗口是最优解,分治法亦可实现(时间复杂度 `O(N log N)`):
1. **分治框架**:将数组分为左右两半,递归求解左右部分的最小窗口。
2. **合并阶段**:检查跨越中间点的子数组,利用前缀和与二分查找优化合并过程。
3. **适用场景**:当问题不限制连续子数组时,分治法可能更灵活,但本题滑动窗口更高效。
---
### 总结
滑动窗口法充分利用了数组元素全为正数的特性,通过动态调整窗口边界,在线性时间内找到最优解,是本题的最佳选择。
阅读全文
相关推荐














