【问题标题】:What is the time complexity of this 5-line Java algorithm?这个 5 行 Java 算法的时间复杂度是多少?
【发布时间】:2018-10-09 11:06:41
【问题描述】:

这是对以下problem的解决方案

基本上,您有一个由“-”和“+”字符组成的字符串:

++-++++

您将两个连续的“+”翻转为“-”,然后您的朋友也这样做,然后再返回给您,依此类推。一旦有人无法移动,他们就输了。

所以对于上面的游戏,如果你先走,你可以通过翻转最后两个“+”或中间两个“+”来获胜(想想看)。

这是一个算法,可以解决先行者是否获胜:

public boolean canWin(String s) {
    for (int i = 0; i < s.length() - 1; ++i)
        if (s.charAt(i) == '+' && s.charAt(i + 1) == '+' && 
            !canWin(s.substring(0, i) + "--" + s.substring(i + 2)))
                return true;
    return false;
}

基本上,该算法递归地表示“如果他能将棋盘缩小到先行者输的状态,则先行者获胜”。

这是我对时间复杂度的看法:

设 N 为棋盘上的字符数。

在最坏的情况下,有 N-1 步(如果都是“+”)。每一步都使棋盘(在最坏的情况下)只小 2 步。

但后来我卡住了。我知道它比 N * (N-2) * (N-4) * ... * 1 差,但我无法制定它。

【问题讨论】:

  • 你的系列 N..1 被调用了 N 次,所以我想是 N^2。
  • 比那更糟糕(想想斐波那契)

标签: java algorithm recursion time-complexity big-o


【解决方案1】:

在最坏的情况下,第一个玩家无法获胜,循环将遍历所有迭代。将问题大小 n 设为输入字符串中的加号数,我们的运行时间为 T(n)=(n-1)T(n-2)=(n-1)(n-3) T(n-4)=...=O(n!!)。在这里,n!是双阶乘。这比指数要差得多,指数对于这个问题来说是相当可怕的。您可以使用如下动态编程来改善这个界限:

Set<String, Boolean> canWinMap = new HashMap<>();

public boolean canWin(String s) {
    if (canWinMap.hasKey(s)) {
        return canWinMap.get(s);
    }
    for (int i = 0; i < s.length() - 1; ++i)
        if (s.charAt(i) == '+' && s.charAt(i + 1) == '+' && 
            !canWin(s.substring(0, i) + "--" + s.substring(i + 2)))
                canWinMap.put(s, true);
                return true;
    canWinMap.put(s, false);
    return false;
}

那么最坏的情况是由一个指数(可能乘以一个线性项)为界的,因为只有 O(2^n) 个可能的字符串来自包含“+”和“-”的起始字符串。在此之后,所有递归调用都是恒定时间(摊销)。

【讨论】:

    猜你喜欢
    • 2015-06-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-03
    相关资源
    最近更新 更多