2
public  String starString(int n){               
    int m = (int)Math.pow(2,n);
    String str="";
    str = starString(m-1,str);                  
    return str;
}
private  String starString(int n, String str){          
    String temp ="";
    if (n<0) {
        try{
            throw new IllegalArgumentException();
        } 
        catch(IllegalArgumentException ex){               
        }          
    }
    else { 
        temp+=("*");              
        starString(n-1,str);        
    }                       
    return temp;       
}

有人可以向我解释为什么这个代码返回一个星号,即使它被一个大于的值调用n >= 0

我调试并注意到在抛出异常后它再次递归并且所有星号都被切成“”。我已经试过很多次了。它还要求你应该抛出IllegalArgumentExceptionif n < 0

4

2 回答 2

6

在 Java 中,字符串是不可变的,因此您需要为temp(并temp作为参数传递)分配一个新值:

temp = starString(n-1, temp);        

此外,您需要分配strto temp,否则每个递归只会返回一个星号:

String temp = str;

递归方法的更简单、更清晰(和正确)的版本如下所示:

private  String starString(int n){          
  String temp = "*";

  //only recurse as long as n > 0, i.e. the last invocation would be made with n = 0
  if (n > 0){ 
    temp += starString(n-1);                     
  }                      
  return temp;       
}

请注意,您甚至不需要将字符串作为参数传递。另请注意,递归在这里是多余的,使用循环将毫无意义。另请注意,字符串连接的成本很高,并且对于较高的值n(由于一遍又一遍地创建不可变的字符串实例)会很快变慢。在这种情况下,您最好使用StringBuilder

private  String starString(int n){          
  StringBuilder s = new StringBuilder();
  for( int i = 0; i <= n; i++ ) {
    s.append("*");
  }
  return s.toString();
}

在我的机器上,对于 n = 100000,使用字符串连接的循环版本大约需要 12 秒,而StringBuilder版本需要 0.007 秒。

于 2012-05-10T19:20:37.210 回答
4

您的代码调用每个递归,存储一个 local temp,返回 this 并且它从未使用过。

于 2012-05-10T19:20:57.537 回答