如何绕过递归限制破解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
相关产品推荐
相关产品推荐

