【问题标题】:Runtime of 2 Keys Keyboard recursive algorithm2键键盘递归算法的运行时间
【发布时间】:2020-08-29 23:52:09
【问题描述】:

最近我偶然发现了一种称为 2 Keys Keyboard 的算法。问题陈述如下:

最初在记事本上只有一个字符“A”。对于每个步骤,您可以在此记事本上执行两个操作:

全部复制:您可以复制记事本上的所有字符(不允许部分复制)。 粘贴:可以粘贴上次复制的字符。

给定一个数字 n。您必须通过执行允许的最小步骤数在记事本上准确地获得 n 'A'。输出得到 n 'A' 的最小步数。

示例 1:

输入:3 输出:3 解释: 最初,我们有一个字符“A”。 在步骤 1 中,我们使用 Copy All 操作。 在第 2 步中,我们使用粘贴操作来获取“AA”。 在第 3 步中,我们使用粘贴操作来获取 'AAA'。

注意:

n 将在 [1, 1000] 范围内。

来源:Leetcode.com:https://leetcode.com/problems/2-keys-keyboard/

我想出了一个可以正常工作的递归解决方案。但是我对它的运行时感到困惑。这是我的递归算法:

class Solution {
public int minSteps(int n) {
    if(n == 1){
        return 0;
    }
    return recursiveDriver(1, 1, n, 1);
}

public int recursiveDriver(int currCount, int totalOperationsSoFar, int target, int previousCopy){
   
    if(currCount == target){
        return totalOperationsSoFar;
    }
    if(currCount > target || previousCopy > target){
         return Integer.MAX_VALUE;
    }
    int countAfterAddingPreviousCopy = currCount+previousCopy;
    int previousCopyVersion = recursiveDriver(countAfterAddingPreviousCopy, totalOperationsSoFar+1, target, previousCopy);
    int pastePreviousAndCopyVersion = recursiveDriver(countAfterAddingPreviousCopy, totalOperationsSoFar+2, target, countAfterAddingPreviousCopy);
    int minNeeded = Integer.min(previousCopyVersion, pastePreviousAndCopyVersion);
    return minNeeded;
}  
}

我认为运行时间会是 O(2^n),但在最坏的情况下会是多少?

【问题讨论】:

    标签: algorithm recursion


    【解决方案1】:

    您的算法的运行时间是O(n),因为它会找到一种方法来获取1..n 范围内的每个数字,然后最多调用一次可能超出范围的更大数字。

    有一个O(log(n)) 版本。仔细想想n 的基数 2 表示以找到它。

    【讨论】:

      【解决方案2】:

      时间复杂度肯定不是O(n),因为除了由一个副本然后所有粘贴组成的线性解决方案之外,还有很多其他的(包括那些超出目标的)。 p>

      我无法确定它,但从取样来看,它看起来非常接近 O(n7/4)

      但是有一个 O(logn) 解决方案:

      想想 17 岁的解决方案是什么:

      真的没有别的办法,就是复制,然后粘贴16次。原因是最后一个粘贴扩展必须的大小必须是n的适当除数。并且 17 没有除 1 之外的其他适当除数。因此,您只能通过粘贴大小 1 来达到 17。

      事实上,当您仔细考虑时:所有粘贴必须是n的除数。

      而且由于我们想要最大化我们粘贴的大小(以更快地到达目标),您开始意识到您需要收集 n 的所有素除数,包括潜在的多次出现一个素数的除数(比如 2 除以 8 三倍)。

      例如,当 n 为 45 时,我们有素数除数 3² 和 5。因此解决方案是:

      复制、粘贴、粘贴(制作 3)
      复制、粘贴、粘贴(制作 3²)
      复制、粘贴、粘贴、粘贴、粘贴(制作 3².5)

      注意每一行如何有许多对应于主要因素的操作。所以我们需要质数除数的sum(包括那些的重复项)。

      因此最终的实现可以是:

      class Solution {
          public int minSteps(int n) {
              // sum prime factors
              int sum = 0;
              int div = 2;
              while (n > 1) {
                  while (n % div == 0) {
                      n /= div;
                      sum += div;
                  }
                  div++;
              }
              return sum;        
          }
      }
      

      您可以使用所谓的“车轮分解”进一步优化,但对于这个挑战(仅限于 n )并没有真正带来太多收益。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-12-12
        • 1970-01-01
        • 2015-02-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多