Java 我的Count和Say递归解决方案的空间复杂度是多少?
给定一个数字序列:1,11,21,121111221… 在序列中生成数字的规则如下: 1是“1”,所以11。 11是“两个1”,所以是21。 21是“一个2后面跟着一个1”,所以1211。 在这个序列中找到第n个数字。 假设: n从1开始,第一个数字是“1”,第二个数字是“11” 我的解决方案:Java 我的Count和Say递归解决方案的空间复杂度是多少?,java,algorithm,recursion,space-complexity,Java,Algorithm,Recursion,Space Complexity,给定一个数字序列:1,11,21,121111221… 在序列中生成数字的规则如下: 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 Str
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;
}
公共字符串countAndSay(int n){
列表结果=helper(n);
StringBuilder sb=新的StringBuilder();
for(整数num:result){
某人追加(num);
}
使某人返回字符串();
}
私有列表帮助器(int n){
列表结果=新建ArrayList();
//基本情况
如果(n==1){
结果.增加(1);
返回结果;
}
列表较小=帮助者(n-1);
整数计数=1;
对于(int i=0;i<更小的.size();i++){
如果(i+1>更小.size()-1||
!small.get(i+1).等于(small.get(i))){
结果。添加(计数);
结果.add(较小的.get(i));
计数=1;
}否则{
计数++;
}
}
返回结果;
}
我对大O符号空间复杂性的理解是,当方法运行时,最大可能的额外空间不会等待垃圾收集。
因此,我对这个解决方案的空间复杂性的看法是,由于递归调用是由行“List smaller=helper(n-1);”完成的,因此用于较低级别递归调用的额外空间已经在等待垃圾收集。因此,低级别的时间复杂度不应计入当前级别。该解的空间复杂度应为O(n)。我说得对吗?是的,从java的角度看,你是对的。大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();
}
此处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++;
}
}
int count=1;
对于(int i=0;i<更小的.size();i++){
如果(i+1>更小.size()-1||
!small.get(i+1).等于(small.get(i))){
结果。添加(计数);
结果.add(较小的.get(i));
计数=1;
}否则{
计数++;
}
}
您可以使用笔、纸或调试来查看递归罩下的实际情况 是的,从java的角度来看,你是对的。大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();
}
此处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++;
}
}
int count=1;
对于(int i=0;i<更小的.size();i++){
如果(i+1>更小.size()-1||
!small.get(i+1).等于(small.get(i))){
结果。添加(计数);
结果.add(较小的.get(i));
计数=1;
}否则{
计数++;
}
}
您可以使用笔、纸或调试来查看递归罩下的实际情况 非常感谢您的回答,并给了我一个更好的解决方案!我对细节还有些困惑。当我们调用help(1)时,所有help(2)到help(n)都在递归堆栈中,但在那个时候,每个堆栈的空间复杂度是O(1),因为我们只创建了一个空列表,最大空间复杂度是(n-1)*O(1)+O(n)(这是helper(1)的列表))=O(n)。我想确定的是这个分析是否正确。另一件让我困惑的事情是,输入大小是恒定的,但空间和时间的复杂性随着输入值的增加而增加。说空间复杂度是O(1)安全吗?再次感谢你的回答!这是一个非常详细的答案。我想我现在明白你的意思了!非常感谢您的回答,并给了我一个更好的解决方案!我对细节还有些困惑。当我们调用help(1)时,所有help(2)到help(n)都在递归堆栈中,但在那个时候,每个堆栈的空间复杂度是O(1),因为我们只创建了一个空列表,最大空间复杂度是(n-1)*O(1)+O(n)(这是helper(1)的列表))=O(n)。我想确定的是这个分析是否正确。另一件让我困惑的事情是,输入大小是恒定的,但空间和时间的复杂性随着输入值的增加而增加。说空间复杂度是O(1)安全吗?再次感谢你的回答!这是一个非常详细的答案。我想我现在明白你的意思了!