2017-08-28 79 views
0

我尝试了一个按位和程序之间的数字范围的a和b。 可以有'n'个测试用例。
0<=a,b<=2^32
1<=n<=200递归调用中的StackOverFlow异常

说明
1
2 4
计算:2&3&4

INPUT
1
4009754624 4026531839

输出
Exception in thread "main" java.lang.StackOverflowError at Example.BitwiseAnd.calculate(BitwiseAnd.java:78)

CODE

public class BitwiseAnd 
{ 
    static long temp = 0; 
    static long result[]; 

    public static void main(String[] args) 
    { 
     Scanner scan = new Scanner(System.in); 
     int time = scan.nextInt(); 
     if(validateTime(time)) 
     { 
      result = new long[time]; 
      for(int i=0;i<time;i++) 
      { 
       long arr[] = new long[2]; 
       arr[0] = scan.nextLong(); 
       temp=arr[0]; 
       arr[1] = scan.nextLong(); 
       if(validateNum(arr[0],arr[1])) 
       { 
        result[i] = calculateUsingRecursion(arr[0],arr[1]); 
        //result[i] = calculateUsingForLoop(arr[0],arr[1]); 
       } 
       else 
       { 
        System.out.println("Enter a valid numbers"); 
       } 
      } 
      printResult(result); 
     } 
     else 
     { 
      System.out.println("Enter a valid number of testcases"); 
     } 
    } 

    public static void printResult(long[] result) 
    { 
     for(int i=0;i<result.length;i++) 
     { 
      System.out.println(result[i]); 
     } 
    } 

    public static boolean validateNum(long num1, long num2) 
    { 
     Long max = (long)Math.pow(2, 32); 
     if(num1<0 || num1>max) 
     { 
      return false; 
     } 
     else if(num2<0 || num2>max) 
     { 
      return false; 
     } 
     return true; 
    } 

    public static boolean validateTime(int time) 
    { 
     if(time<1 || time>200) 
     { 
      return false; 
     } 
     return true; 
    } 

    private static long calculateUsingRecursion(long num1, long num2) 
    { 
     while(num1<num2) 
     { 
      num1=num1+1; 
      temp=temp&num1; 
      calculateUsingRecursion(num1, num2); 
     } 
     return temp; 
    } 

    private static long calculateUsingForLoop(long num1,long num2) 
    { 
     num1=num1+1; 
     for(long i=num1 ; i<=num2 ; i++) 
     { 
      temp=temp&num1; 
     } 
     return temp; 
    } 
} 

递归方法计算被扔我StackOverFlowException,对于大组数字。而循环工作正常。 这里我的问题是为什么我们不能有大量输入的递归?以及如何用递归修复?

+0

添加异常的堆栈跟踪将是有用的。 – araknoid

+0

它适用于递归,但需要足够的内存来存储各个堆栈。你的情况你可以配置你的JVM为此提供更多的内存:https://stackoverflow.com/questions/3700459/how-to-increase-the-java-stack-size –

+0

'“为什么我们不能有递归对于大量的输入“' - 因为调用栈是有限的。 – David

回答

1

您没有添加所有信息(如完整的堆栈跟踪),并且代码中没有BitwiseAnd.calculate方法。

1)在递归方法中使用“while”,但不应循环,因为这是递归调用完成的,您应该使用“if”来代替。

2)堆栈的大小是有限的,所以一个方法不能在无限循环中调用自己。输入4009754624和4026531839必须自己调用16777215次。背景需要更多内存。但为了简化它:Java必须为您的方法分配2个长参数16777215次,并且只能在每个方法返回后重用它们。

所以如果你做了很多迭代,就不要做递归调用。

1

你的递归函数是迭代和递归之间的混合。像这样改变它:

private static long calculateUsingRecursion(long num1, long num2, long temp) { 

    // Stop condition 
    if (num1 >= num2) { 
     return temp; 
    }  

    // Progression 
    num1 = num1 + 1; 
    temp = temp & num1; 

    // Recursion 
    return calculateUsingRecursion(num1, num2, temp);   
} 

请注意,如果任何递归函数递归过深,您将得到一个StackOverflowException。

+1

这将仍然给堆栈溢出的'num2'和'num1'的巨大差异。 –

+0

当然,这是任何递归函数的问题。也许这是一项家庭作业任务,旨在说明为什么递归函数不总是适用。 –

1

你不需要遍历所有这些数字。您只需要找出间隔中所有数字的常数(否则它们的AND等于零)。

让我们循环遍历从最高位到最低位,并检查ab是否具有相同的此位值。停止迭代,当他们在某个位置有不同的位:

long res = 0; 
for (int bit = 32; bit >= 0; --bit) { 
    long bita = a & (1L << bit); 
    long bitb = b & (1L << bit); 
    if (bita != bitb) break; 
    res |= bita; 
} 

的Runnable:https://ideone.com/pkrUtV