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

递归与记忆化算法出现运行时错误,求解Hackerrank密码破解问题

Fixing Runtime Errors in Recursive + Memoization Password Cracker Solution

Hey there! I’ve worked through this exact problem before, so let’s break down why your recursive approach might be hitting runtime errors and how to fix it.

Common Causes of Runtime Errors

1. Stack Overflow from Deep Recursion

If your login attempt string is long (think hundreds of characters made up of short passwords), your recursive calls can stack up way too deep. Most languages have a default recursion depth limit (Python’s is around 1000), and exceeding that will throw a stack overflow error.

2. Inefficient Memoization Leading to Timeouts

If your memoization only tracks whether a position is solvable (a boolean) instead of storing the actual password path, you’ll end up re-computing paths over and over. This leads to exponential time complexity, which will time out for larger test cases (Hackerrank counts timeouts as runtime errors too).

3. Mishandled Edge Cases

Forgetting to handle edge cases like:

  • No valid password combination (needing to return "WRONG PASSWORD" instead of crashing)
  • Prefixes that match multiple passwords but lead to dead ends later on
  • Going out of bounds when checking substrings

Optimized Recursive + Memoization Solution

Here’s a Python implementation that fixes these issues. I’ll walk through the key improvements:

def password_cracker(passwords, login_attempt):
    from functools import lru_cache
    
    # Speed up password lookups with a set
    password_set = set(passwords)
    # Get max password length to avoid checking unnecessary long prefixes
    max_pass_length = max(len(p) for p in passwords) if passwords else 0
    
    @lru_cache(maxsize=None)
    def crack_from_position(pos):
        # Base case: we've successfully matched the entire string
        if pos == len(login_attempt):
            return []
        # If we've gone beyond the string, this path is invalid
        if pos > len(login_attempt):
            return None
        
        # Try all possible password lengths up to our max length
        for length in range(1, max_pass_length + 1):
            end_pos = pos + length
            if end_pos > len(login_attempt):
                continue  # Don't go out of bounds
            current_substring = login_attempt[pos:end_pos]
            
            if current_substring in password_set:
                # Recursively check the rest of the string
                remaining_result = crack_from_position(end_pos)
                if remaining_result is not None:
                    # Build the full path by adding current password + remaining result
                    return [current_substring] + remaining_result
        
        # No valid password found starting from this position
        return None
    
    # Start cracking from position 0
    result = crack_from_position(0)
    return ' '.join(result) if result is not None else "WRONG PASSWORD"

Key Improvements Explained

  • Set for Password Lookups: Checking if a substring is a valid password is O(1) instead of O(N) with a list, cutting down on lookup time.
  • Max Password Length: We don’t waste time checking prefixes longer than the longest password in our list—this reduces unnecessary recursive calls drastically.
  • Memoize the Path: Instead of just storing "can we solve from here?", we store the actual list of passwords that solve the substring. This avoids re-computing paths and lets us build the final answer directly.
  • Clear Base Cases: We explicitly handle reaching the end of the string (success) or going past it (failure), preventing infinite loops or incorrect returns.

Additional Tips to Avoid Runtime Issues

  • Test Edge Cases: Make sure to test scenarios where there’s no valid solution, where the login attempt is exactly one password, and where it’s a long chain of short passwords.
  • Custom Memoization for Other Languages: If you’re using a language without built-in memoization (like Java), use a hash map to store results for each position instead of relying on function decorators.
  • Iterative DP as a Fallback: If recursion depth is still a problem, switch to an iterative dynamic programming approach. You can build a DP array where dp[pos] stores the password path from position pos to the end.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 03:51:30