就时间和空间复杂度而言,以下两种字符串置换算法实现中哪个更好?

时间:2019-01-19 23:49:12

标签: algorithm recursion time-complexity permutation space-complexity

  

问题陈述:给定一个字符串,编写一个程序来查找字符串的所有排列。

我已经以两种不同的方式实现了它,根据我的(可能是错误的)时间复杂度分析,第二个执行的计算较少,但是在实时性能方面,第一个优于第二个。

问题:

  1. 我的时间分析正确吗?为什么计算性能不同?

  2. 在空间需求方面,哪些实施方案会更好?

  3. 在递归调用中,我返回的是不可变数据类型,而不是使用可变的累加器(我在某处读到这是一种好习惯)。这是明智的选择吗,还是可以通过使用可变变量或静态变量来实现更好的性能(在空间或时间上)?

  4. 代替返回List还是将其包装为Iterator更好?我读过一个可能更好的地方,因为您无需一次将所有排列都保留在内存中,也不需要预先计算所有排列,然后再对它们进行任何处理。代码看起来如何?

  5. 是否可以通过使用StringBuffer或StringBuilder而不是字符串来进一步优化它?我认为编译器会在使用StringBuilder的情况下自动实现串联,这样可以吗?
  6. 还有其他建议来改进代码吗?

第一个版本:

    private static List<String> permuteOne (String partial, String rest) {
        List<String> result = new ArrayList<>();
        if (rest.length() == 1) {
            result.add(partial + rest); 
        } else {
            for (int j = 0; j < rest.length(); j++) {;
                result.addAll(permuteOne(partial + rest.charAt(j), rest.substring(0,j) + rest.substring(j+1)));
            }
        }
        return Collections.unmodifiableList(result);
    }
  

时间复杂度T(n)= n * T(n-1)

     
    

numOperations(firstVersion)= n + n(n-1)+ n(n-1)(n-2)+ ... n!

  
     

空间复杂度:??

第二版:

    private static List<String> permuteTwo (String remaining) {  
        List<String> newList = new ArrayList<>();
        if (remaining.length() == 1) {
             newList.add(remaining);
        } else {        
            List<String> partialPerms = permuteTwo(remaining.substring(0, remaining.length()-1)); 
            for(String permutation: partialPerms )
                for(int j = 0; j <= permutation.length(); j++){
                    newList.add(permutation.substring(0, j) + remaining.charAt(remaining.length()-1) + permutation.substring(j));
            }   
        }
        return newList;
    }
  

时间复杂度T(n)= n! + T(n-1)

     
    

numOperations(secondVersion)= 1! + 2! + 3! + ... n!   

     

空间复杂度:n * n !? <-不确定

0 个答案:

没有答案