You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

递归实现字符串最小覆盖窗口时遇递归深度超出错误求助

解决递归深度超限问题及最小覆盖子串实现

错误原因分析

你的makeWindow递归函数存在逻辑缺陷,导致无法触发终止条件,进而无限递归:

  • charRemain = setOfallCharacter ^ remainLimChar 的逻辑错误:异或操作返回的是两个集合的对称差集(只在其中一个集合出现的元素),这不是你需要的「剩余未找到的字符」,正确的剩余字符应该是remainLimChar - setOfallCharacter。
  • 递归调用时传递的str1[lenRemain:]会不断缩短字符串,但如果剩余字符串中没有需要的字符,charRemain永远不为空,递归会无限进行,直到触发Python默认的递归深度上限。

修复后的递归实现(不推荐,仍有效率问题)

如果坚持用递归,需要修正逻辑,确保每次递归都能正确减少剩余需要查找的字符,同时处理字符串耗尽的边界情况:

from collections import Counter

def smallestWin(str1):
    all_chars = set(str1)
    min_window = None
    # 遍历所有可能的起始位置
    for i in range(len(str1)):
        window = makeWindow(str1[i:], all_chars.copy())
        if window:
            if not min_window or len(window) < len(min_window):
                min_window = window
    print(min_window)

def makeWindow(s, remain_chars):
    # 终止条件:找到所有字符,或者字符串耗尽
    if not remain_chars:
        return ""
    if not s:
        return None  # 表示无法找到剩余字符
    
    current_char = s[0]
    # 如果当前字符是需要找的,从剩余集合中移除
    if current_char in remain_chars:
        remain_chars.remove(current_char)
    
    # 递归处理剩余字符串
    rest_window = makeWindow(s[1:], remain_chars)
    if rest_window is None:
        return None
    return current_char + rest_window

def main():
    str1 = "asdaewsqgtwwsa"
    smallestWin(str1)

if __name__ == "__main__":
    main()

更优方案:滑动窗口(双指针)法

递归并不适合这类问题,滑动窗口是找最小覆盖子串的标准高效解法,时间复杂度O(n),完全避免递归深度问题:

from collections import Counter

def smallestWin(str1):
    # 统计所有需要包含的字符及其数量
    target = Counter(str1)
    required = len(target)
    # 滑动窗口的左右指针
    left, right = 0, 0
    # 记录窗口中已满足数量要求的字符数
    formed = 0
    # 记录窗口内字符的计数
    window_counts = {}
    # 存储最小窗口的信息:长度,左端点,右端点
    min_window = float("inf"), None, None

    while right < len(str1):
        char = str1[right]
        window_counts[char] = window_counts.get(char, 0) + 1

        # 如果当前字符的数量达到目标要求,formed加1
        if window_counts[char] == target[char]:
            formed += 1

        # 当窗口包含所有字符时,尝试缩小左边界以找到更小窗口
        while left <= right and formed == required:
            char = str1[left]
            # 更新最小窗口
            current_window_len = right - left + 1
            if current_window_len < min_window[0]:
                min_window = (current_window_len, left, right)
            
            # 移除左指针的字符,更新窗口计数
            window_counts[char] -= 1
            if window_counts[char] < target[char]:
                formed -= 1
            
            left += 1
        
        right += 1
    
    # 返回最小窗口,若不存在则返回空字符串
    return str1[min_window[1]:min_window[2]+1] if min_window[0] != float("inf") else ""

def main():
    str1 = "asdaewsqgtwwsa"
    print(smallestWin(str1))

if __name__ == "__main__":
    main()

说明

滑动窗口通过左右指针动态调整窗口大小,在一次遍历中找到最小覆盖子串,既解决了递归深度问题,又大幅提升了运行效率。递归方案虽能修复,但对于较长字符串仍会出现性能瓶颈,因此更推荐滑动窗口解法。

内容的提问来源于stack exchange,提问作者Kise Nguyen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 19:40:22