【问题标题】:How to find the time complexity of dfs+backtracking algorithms?如何求dfs+回溯算法的时间复杂度?
【发布时间】:2018-01-21 14:19:21
【问题描述】:

我正在尝试在 leetcode https://leetcode.com/problems/factor-combinations/description/ 上解决这个问题

数字可以看作是其因子的乘积。例如

8 = 2 x 2 x 2; = 2 x 4。

编写一个接受整数 n 并返回其因子的所有可能组合的函数。

虽然我能够使用 dfs 方法编写代码,但我很难在输入方面驱动其最坏情况的时间复杂度。有人可以帮忙吗?

 public List<List<Integer>> getFactors(int n) {
        List<List<Integer>> result = new ArrayList<List<Integer>>();
        List<Integer> current = new ArrayList<Integer>();
        getFactorsHelper(n,2,current,result);
        return result;
    }
    
    
    public void getFactorsHelper(int n,int start,List<Integer> current, List<List<Integer>> result){
        if(n<=1 && current.size()>1){
            result.add(new ArrayList<>(current));
            return;
            
        }
        for(int i=start;i<=n;i++){
          
            if(n%i==0) {
                current.add(i);
                getFactorsHelper(n/i,i,current,result);
                current.remove(current.size()-1);
            }            
            
        }
        
    }

【问题讨论】:

  • 相对于什么变量的时间复杂度?
  • 关于输入 n
  • 好的,但请记住,它会有很大的波动 - 例如 127 只有一个输出,而 128 有负载。
  • 是的。我对最坏情况的复杂性感兴趣。
  • 这里的“最坏情况”是什么意思? (我并不是想变得困难,我想指出您的问题可能没有意义,因为它目前提出。)

标签: java algorithm recursion time-complexity depth-first-search


【解决方案1】:

我这样计算您的代码的复杂性:

假设getFactorsHelper(n,2)runtime 是函数T(n)

在下面的部分中,您有一个带有i 索引的循环。

for(int i=start;i<=n;i++){    
            if(n%i==0) {
                current.add(i);
                getFactorsHelper(n/i,i,current,result);
                current.remove(current.size()-1);
            }              
        }

n 在每次迭代中除以i。所以我们有:

(第一次迭代)

getFactorsHelper(n/2,2,current,result) = T(n/2) 

(第二次迭代)

getFactorsHelper(n/3,3,current,result) <= getFactorsHelper(n/3,2,current,result) = T(n/3) 

(第三次迭代)

getFactorsHelper(n/4,4,current,result) <= getFactorsHelper(n/4,2,current,result) 
= T(n/4) 

...

(最终迭代)

getFactorsHelper(n/n,n,current,result) <= getFactorsHelper(n/n,2,current,result) = T(n/n) = T(1) 

总费用

T(n) <= T(n/2) + T(n/3) + T(n/4) + ... + T(1)

求解递归函数

希望对你有帮助。

【讨论】:

  • 感谢阿里详细解答。如果我必须以更简化的方式理解。第一次调用 getFactorsHelper 时,总共有 n 次可能的迭代(因为 2 到 n 次 for 循环)。我对每次迭代中完成的工作感到困惑的部分。
  • @KBR 对不起,我在计算循环顺序时出错了!!。我又解决了。请看。
  • 谢谢阿里。所以它的 O(nlogn) ..对吗?很抱歉问这个问题是我想从大学时代回忆起来的一些数学符号
  • @KBR 是 O(nlnn) = O(nlogn).
  • 嗨@AliSoltani你能帮忙this solution吗? KBR 发布的解决方案在 leetcode 中大约需要 210 毫秒,而后续只需要 2 毫秒。根据您的分析,慢速解决方案是 O(nlogn),所以快速解决方案应该是 O(n)?
【解决方案2】:

无法在评论中发布解决方案。在这里发布另一个答案@AliSoltani https://discuss.leetcode.com/topic/30752/my-short-java-solution-which-is-easy-to-understand

public class Solution {
public List<List<Integer>> getFactors(int n) {
    List<List<Integer>> ret = new LinkedList<List<Integer>>();
    if(n <= 3)  return ret;
    List<Integer> path = new LinkedList<Integer>();
    getFactors(2, n, path, ret);
    return ret;
}

private void getFactors(int start, int n, List<Integer> path, List<List<Integer>> ret){
   for(int i = start; i <= Math.sqrt(n); i++){
       if(n % i == 0 && n/i >= i){  // The previous factor is no bigger than the next
           path.add(i);
           path.add(n/i);
           ret.add(new LinkedList<Integer>(path));
           path.remove(path.size() - 1);
           getFactors(i, n/i, path, ret);
           path.remove(path.size() - 1);
       }
   }
}}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多