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

如何绕过递归限制破解n位小写字母密码?

递归破解密码的栈溢出问题及解决方案

问题背景

需破解长度为n的纯小写字母密码,任务限制如下:

  • 禁止使用循环,仅允许递归
  • 仅能通过黑盒Password类的isPassword()方法验证完整密码,无法逐字符校验
  • String类仅可使用charAt、equals、length、substring方法
  • 不可使用其他类
  • 不可硬编码26行调用传入单个字母

当前实现代码可处理2位、偶尔3位密码,但n≥4时,因需26⁴、26⁵次递归调用,栈深度远超Java默认限制(约2000层),触发栈溢出。现有代码如下:

public static String findPassword (Password p, int length){
    return findPassword(p, length, "");
}

private static String findPassword(Password p,int length, String str){
    if(str.length()<length){
        str+='a';
        findPassword(p,length, str);
    }
    if(p.isPassword(str)){
        return str;
    }
    return findPassword(p,length,changeString(str,0));
}

private static String changeString(String str, int index){
    if(str.charAt(index) == 'z'){
        str = str.substring(0, index) + 'a' + str.substring(index + 1);
        return changeString(str,index + 1);
    }
    return str.substring(0, index) + (char)(str.charAt(index) + 1) + str.substring(index + 1);
}

核心问题本质

栈溢出的根源是递归栈深度(未返回的方法层数)过高,而非总调用次数。原代码中每生成一个密码候选就发起一次递归,栈深度等于候选总数26^n,远超栈容量限制。

解决方案:分治递归(彻底规避栈溢出)

通过将n位密码拆分为前后两个子段(如前k位和后n-k位),把线性深度递归转为分层递归,将栈深度严格控制在O(n)级别(远小于栈限制)。

改造后代码

public static String findPassword(Password p, int length) {
    if (length == 0) {
        return p.isPassword("") ? "" : null;
    }
    int splitLen = length / 2;
    return traverseLeftPart(p, splitLen, "", length - splitLen);
}

private static String traverseLeftPart(Password p, int leftRemaining, String currentLeft, int rightTotal) {
    if (leftRemaining == 0) {
        String result = traverseRightPart(p, currentLeft, rightTotal, "");
        if (result != null) {
            return result;
        }
    } else {
        String result = traverseLeftPart(p, leftRemaining - 1, currentLeft + 'a', rightTotal);
        if (result != null) {
            return result;
        }
        return incrementLeftPart(p, leftRemaining, currentLeft, rightTotal, currentLeft.length());
    }
    return null;
}

private static String incrementLeftPart(Password p, int leftRemaining, String currentLeft, int rightTotal, int index) {
    if (index >= currentLeft.length()) {
        return null;
    }
    char currentChar = currentLeft.charAt(index);
    if (currentChar == 'z') {
        String updatedLeft = currentLeft.substring(0, index) + 'a' + currentLeft.substring(index + 1);
        return incrementLeftPart(p, leftRemaining, updatedLeft, rightTotal, index + 1);
    }
    String updatedLeft = currentLeft.substring(0, index) + (char)(currentChar + 1) + currentLeft.substring(index + 1);
    String result = traverseLeftPart(p, leftRemaining, updatedLeft, rightTotal);
    if (result != null) {
        return result;
    }
    return incrementLeftPart(p, leftRemaining, updatedLeft, rightTotal, index);
}

private static String traverseRightPart(Password p, String leftStr, int rightRemaining, String currentRight) {
    String fullPassword = leftStr + currentRight;
    if (p.isPassword(fullPassword)) {
        return fullPassword;
    }
    if (rightRemaining == currentRight.length()) {
        return null;
    }
    String result = traverseRightPart(p, leftStr, rightRemaining, currentRight + 'a');
    if (result != null) {
        return result;
    }
    return incrementRightPart(p, leftStr, rightRemaining, currentRight, currentRight.length());
}

private static String incrementRightPart(Password p, String leftStr, int rightRemaining, String currentRight, int index) {
    if (index >= currentRight.length()) {
        return null;
    }
    char currentChar = currentRight.charAt(index);
    if (currentChar == 'z') {
        String updatedRight = currentRight.substring(0, index) + 'a' + currentRight.substring(index + 1);
        return incrementRightPart(p, leftStr, rightRemaining, updatedRight, index + 1);
    }
    String updatedRight = currentRight.substring(0, index) + (char)(currentChar + 1) + currentRight.substring(index + 1);
    String fullPassword = leftStr + updatedRight;
    if (p.isPassword(fullPassword)) {
        return fullPassword;
    }
    String result = traverseRightPart(p, leftStr, rightRemaining, updatedRight);
    if (result != null) {
        return result;
    }
    return incrementRightPart(p, leftStr, rightRemaining, updatedRight, index);
}

方案说明

  • 递归深度严格控制在2*n层以内(生成前半部分最多n层,生成后半部分最多n层),完全不会触发栈溢出
  • 符合所有任务限制:无循环、仅用允许的String方法、未使用其他类、未硬编码字母调用
  • 遍历逻辑完整,覆盖所有n位小写字母组合

内容的提问来源于stack exchange,提问作者ori ben dror

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 17:15:23