Count和Say的递归解决方案的空间复杂性是多少?

时间:2017-04-26 04:03:51

标签: java algorithm recursion space-complexity

给出一系列数字:1,11,21,1211,111221,...... 生成序列中的数字的规则如下: 1是"一个1"所以11。 11是"两个1"所以21。 21是"一个2然后是一个1"所以1211。 找到此序列中的第n个数字。 假设: n从1开始,第一个数字是" 1",第二个数字是" 11"

我的解决方案:

public String countAndSay(int n) {
List<Integer> result = helper(n);
StringBuilder sb = new StringBuilder();
for(Integer num : result) {
      sb.append(num);
}
return sb.toString();
}

private List<Integer> helper(int n) {
List<Integer> result = new ArrayList<Integer>();
//base case
if (n == 1) {
     result.add(1);
     return result; 
}
List<Integer> smaller = helper(n - 1);
int count = 1;
for (int i = 0; i < smaller.size(); i++) {
    if (i + 1 > smaller.size() - 1 ||
              !smaller.get(i + 1).equals(smaller.get(i))) {
         result.add(count);
         result.add(smaller.get(i));
         count = 1;
    } else {
         count++;
    }
}
    return result;
}

我对大O符号空间复杂性的理解是,当方法运行时,最大可能的额外空间不等待垃圾收集。 所以我对这个解决方案的空间复杂性的思考是因为递归调用是由行&#34; List smaller = helper(n-1);&#34;完成的,递归调用的较低级别的额外空间是已经在等待垃圾收集了。因此,低级别的时间复杂性不应该是t计入当前水平。该解决方案的空间复杂度应为O(n)。我是对的吗?

1 个答案:

答案 0 :(得分:0)

是的,在java透视中,你是对的。 Big O表示随着输入大小的增加表示空间/时间的增长顺序。代码占用的空间量将随着n输入的增加而线性增加。因此,此解决方案的空间复杂性确实是O(n)

对于递归,空间复杂性涉及在最坏情况下在递归/函数堆栈中占用的空间。因为当前在递归堆栈中的函数调用不符合当前的垃圾回收调用。调用helper(1)时此程序将占用的最大空间,因为此时helper(n), helper(n - 1) .... helper(2)使用本地资源进行的所有调用都在递归堆栈中,并且不符合垃圾回收的条件。

但是,您可以在没有递归的情况下在恒定空间中执行此操作。

public String countAndSay(int n) {
        StringBuilder curr = new StringBuilder("1");
        StringBuilder prev;
        int count;
        char say;
        for (int i = 1; i < n; i++) {
            prev = curr;
            curr = new StringBuilder();       
            count = 1;
            say = prev.charAt(0);

            for (int j = 1, len = prev.length(); j < len; j++) {
                if (prev.charAt(j) != say){
                    curr.append(count).append(say);
                    count = 1;
                    say = prev.charAt(j);
                }
                else count++;
            }
            curr.append(count).append(say);
        }                   
        return curr.toString();

}

希望它有所帮助!

修改

  

我仍然对细节感到困惑。当我们打电话给帮助(1)时,   所有帮助(2)帮助(n)是递归堆栈,但在那个时候,   每个堆栈的空间复杂度为O(1),因为我们只创建了一个空的   列表,最大空间复杂度为(n-1)* O(1)+   O(n)(这是助手(1)的列表)= O(n)。我想确定的是   这个分析是正确的。

不,这是递归堆栈的图片。您可以设置断点和调试以查看实际发生的情况。

call           result size(when entered)    result size(when function returns)
helper(n)        0                               x(n)
helper(n - 1)    0                               x(n - 1)
helper(n - 2)    0                               x(n - 2)
.......
......
helper(3)        0                               x2
helper(2)        0                               x1
helper(1)        0                               1

此处x(i)是执行此块后的结果大小:

int count = 1;
for (int i = 0; i < smaller.size(); i++) {
    if (i + 1 > smaller.size() - 1 ||
              !smaller.get(i + 1).equals(smaller.get(i))) {
         result.add(count);
         result.add(smaller.get(i));
         count = 1;
    } else {
         count++;
    }
}

您可以使用纸笔或调试来查看递归引擎下真正发生的事情。