【问题标题】:What is causing StackoverFlowError in my code?是什么导致我的代码中出现 StackoverFlowError?
【发布时间】:2019-09-17 11:51:30
【问题描述】:

我需要写两个recusion方法。其中之一检查需要从其最高有效数字到最低有效数字枚举的候选值。例如,如果数字是三位数,则它需要是 124 126 128 134 136 138 146 148 156 等等,直到 999(也是偶数)。

我写了其中两个,一位,两位和三位数字没有问题,但是,在四位数字之后会导致 java.lang.StackOverflowError 我该如何解决这个问题?

  public boolean checkRec(int num)
   {
      String numLong = String.valueOf(num);
      if((Integer.valueOf(numLong.substring(numLong.length()-1)) % 2) != 0)
         return false;      
      if(numLong.length() == 1)
         return true;
      else
      {
         if(Integer.valueOf(numLong.substring(0,1)) >= Integer.valueOf(numLong.substring(1,2)))
         {
           // System.out.println("asd");
          return false;
         }
         numLong = numLong.substring(1);
         num = Integer.valueOf(numLong);
         return checkRec(num);
      }
   }
public String orderAndPrint(int num, int decimal)
       {
          if(num >= Math.pow(10, decimal+1))
            return "End";
          else
          {
             if(checkRec(num))
             {
                return "" + num + " " + orderAndPrint((num + 2), decimal);
             }
             return orderAndPrint((num + 2), decimal);
          }

【问题讨论】:

  • 你只是有一个非常深的递归,因为你在大范围的值上加紧了 2 秒。唯一的选择是增加你的最大调用堆栈深度,或者不递归那么深(例如,使用循环代替)。
  • 因为这是尾递归,您可以将其简化为循环。它是继承迭代的。

标签: java recursion integer stack stack-overflow


【解决方案1】:

你确实喜欢递归 :-)。这个函数对怎么样:

public boolean check(int num)
{
    // This is actually unnecessary as check is called only for even numbers
    if ((num % 2) != 0)
        return false;
    int prev_digit = 10;
    while (num > 0) {
        int last_digit = num % 10;
        if (last_digit >= prev_digit)
            return false;
        prev_digit = last_digit;
        num = num / 10;
    }
    return true;
}

public String orderAndPrint(int decimal)
{
    String outstr = ""
    int last_num = Math.pow(10, decimal);
    int num = 2;
    for ( ; num < last_num; num += 2) {
        if (check(num))
            outstr = outstr + num + " ";
    }
    return outstr + "End";
}

但是,这段代码只是更有效地复制了您所做的事情,没有递归。

但是,您可以编写代码来生成适当的数字,而您实际上需要递归。请注意,此类数字的最大可能为 12345678,因此最大位数为 8,并且所有此类数字都适合 int。此外,没有一个数字会大于 8,只有最后一位可能是 8。

public String addnumbers (int n, int digitsleft, String outstr)
{
    int d;
    int last_digit = n % 10;
    if (digitsleft == 1) {
        d = (last_digit+1) % 2 == 0 ? last_digit+1 : last_digit+2;
        for ( ; d <= 8; d += 2) {
            outstr = outstr + (10*n+d) + " ";
        }
    }
    else {
        for (d=last_digit+1; d < 8; ++d) {
            outstr = addnumbers(10*n+d, digitsleft-1, outstr);
        }
    }
    return outstr;
}
public String orderAndPrint(int decimal)
{
    // Assume decimal is at least 1
    String outstr = "2 4 6 8 "
    int d;

    decimal = Math.min(8, decimal);
    for (d = 1; d < 8; ++d) {
        outstr = addnumbers(d, decimal-1, outstr);
    }
    return outstr + "End";
}

请注意,这可以通过在循环中使用更好的 d 上限来进一步加快速度。例如,如果在当前一位之后还有 2 位以上的数字,则 d 不能大于 6。但这只会混淆代码。

【讨论】:

    猜你喜欢
    • 2021-10-28
    • 1970-01-01
    • 2015-09-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-17
    • 2017-12-13
    • 2020-10-28
    相关资源
    最近更新 更多