【问题标题】:Trouble with recursive method java递归方法java的问题
【发布时间】:2016-12-09 03:31:04
【问题描述】:

基本上我有一个蛮力密码猜测器(我意识到它不是很有效)我有一个过程我想变成一个递归方法,我可以传递一个 length 整数,它将运行那数量的字符。 这是代码:

public static void generatePassword(int length)
{
    // should be a recusive function learn how to do that
    // 1 interval
    for(int i =32;i<127;i++)// ascii table length
    {
                System.out.println((char)i);

    }
    // 2 interval
    for(int z =32;z<127;z++)// ascii table length
    {
        for(int q =32;q<127;q++)// ascii table length
        {
            System.out.println((char)z+""+(char)q);

        }

    }
    // 3 interval
    for(int w =32;w<127;w++)// ascii table length
    {
        for(int o =32;o<127;o++)// ascii table length
        {
            for(int g =32;g<127;g++)// ascii table length
            {
            System.out.println((char)w+""+(char)o+""+(char)g);
            }
        }


    }

}

间隔返回具有该长度示例的字符串:第三个间隔将返回长度为 3 的每个可能的字符串组合。如果有人可以帮助我自动执行此过程并解释(我想学习而不是复制和粘贴)会很好 ! :)

【问题讨论】:

标签: java brute-force


【解决方案1】:

递归方法是一种调用自身的方法,它有一个基本条件(也称为停止条件),可以防止它进入无限循环。

我们以第一个区间为例:

for(int i = 32; i < 127; i++) { // ascii table length
    System.out.println((char)i);
}

我们可以创建一个递归方法来做同样的事情:

private void interval1(int i) {
    if (i < 32 || i >= 127) return;
    System.out.println((char)i);
    interval1(i + 1);
}

为了在我们的用例中使用它,我们应该使用 i=32 调用这个方法:interval(32)

希望这会有所帮助!

【讨论】:

  • 这可以打印出从i 到 127 的字符,但对生成密码没有帮助。
  • @Iluvatar 我的理解是问题的重点是学习如何将迭代代码修改为递归代码。生成密码不是重点。
  • 我的斗争是自动化该过程并打印出长度为 length 的所有可能的单词组合
【解决方案2】:

函数

请注意,这将非常低效。这在实践中不应该这样做,因为创建的 String 对象的数量非常庞大(见答案底部)

public void recursivePrint(String prefix, int levels) {
    if (levels <= 1) {
        for (int i = 33; i < 127; ++i) {
            System.out.println(prefix+(char)i);
        }
    } else {
        for (int i = 33; i < 127; ++i) {
            recursivePrint(prefix+(char)i, levels-1);
        }
    }
}

然后你调用它:

recursivePrint("", 5); // for printing all possible combinations of strings of length 5

工作原理

对函数的每次调用都有自己的内存,并且是单独存储的。当您第一次调用该函数时,有一个名为 prefix 的字符串,其值为“”,一个名为 'levels' 的 int 值为 5。然后,该函数使用新值调用 recursivePrint(),因此新内存是分配,第一个调用将等到这个新调用完成。

这个新调用有一个值为(char)34+"" 的String 前缀和一个值为4 的级别。请注意,这些变量与第一个函数调用完全不同,因为请记住:每个函数调用都有它是自己的记忆(第一个电话正在等待这个完成)。现在第二次调用对 recursivePrint() 函数进行 另一个 调用,产生 更多 内存,并等待新的调用完成。

当我们达到级别 == 1 时,会从之前的调用中建立一个前缀,剩下的就是使用该前缀并打印该前缀的所有不同组合,最后一个字符发生变化。

一般来说,递归方法效率极低,在这种情况下尤其如此。

为什么你不应该使用它

不过,这种方法不仅效率低下;对于任何有用的东西都是不可行的。让我们计算一下:5 个字符的字符串有多少种不同的可能性?好吧,您要选择 127-33=94 个不同的字符,那么这意味着每个字符有 94 个选择。那么可能性的总数是 94^5 = 7.34*10^9 [不包括存储每个字节的 5+ 个字节](从角度来看,4GB 的 RAM 大约是 4*10^9 字节)

【讨论】:

    【解决方案3】:

    这是您使用递归实现的方法:

    public static void generatePassword(int length, String s) {
            if (length == 0) {
                System.out.println(s);
                return;
            }
            for (int i = 32; i < 127; i++) {
                String tmp  = s+((char) i);
                generatePassword(length - 1, tmp);
            }
        }
    

    您所要做的就是将长度和初始字符串(即“”)传递给它。
    在 if 语句中检查是否应停止递归(当生成的密码长度等于预期时)。
    在 for 循环中,将新字符添加到实际字符串中,并以较短的长度和新字符串作为参数调用该方法。

    希望对您有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-08-01
      • 2014-01-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多