2017-08-28 58 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