给出一系列数字: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)。我是对的吗?
答案 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++;
}
}
您可以使用纸笔或调试来查看递归引擎下真正发生的事情。