【问题标题】:Stack overflow in recursive method递归方法中的堆栈溢出
【发布时间】:2017-08-26 06:10:57
【问题描述】:

我正在编写一个程序,允许用户将一组整数输入到数组中,一旦输入零,就会显示这些数字的特征。我对一种方法有疑问:findMaxOfLessThanFirst。当然,它会在数组中找到也小于输入的第一个数字的最大数字。完整代码如下:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Assignment9 {
    public static void main(String[] args) throws IOException {
        int index = 0;
        int[] numbers;
        numbers = new int[100];

        InputStreamReader inRead = new InputStreamReader(System.in);
        BufferedReader buffRead = new BufferedReader(inRead);
        String line = buffRead.readLine();

        try {
            while (!line.equals("0") && index < 100) {
                numbers[index] = Integer.parseInt(line);
                index++;
                line = buffRead.readLine();
            }
        } catch (IOException exception) {
            System.out.println("Array index out of bound");
        }
        int min = findMin(numbers, 0);
        int sumAtEven = computeSumAtEvenIndexes(numbers, 0, numbers.length - 1);
        int divByThree = countDivisibleBy3(numbers, 0, numbers.length - 1);
        int maxLessThanFirst = findMaxOfLessThanFirst(numbers, 1, numbers.length - 1, numbers[0]);
        System.out.println("The minimum number is " + min);
        System.out.println("The sum of numbers at even indexes is " + sumAtEven);
        System.out.println("The count of numbers that are divisible by 3 is " + divByThree);
        System.out.println(
                "The maximum number among numbers that are less than the first number is " + maxLessThanFirst);
    }

    public static int findMin(int[] numbers, int index) {
        if (index == numbers.length - 1) {
            return numbers[index];
        } else {
            return Math.min(numbers[index], findMin(numbers, index + 1));
        }
    }

    public static int computeSumAtEvenIndexes(int[] numbers, int startIndex, int endIndex) {
        if (startIndex == endIndex) {
            if (startIndex % 2 == 0) {
                return numbers[startIndex];
            } else
                return 0;
        } else {
            if (endIndex % 2 == 0) {
                return computeSumAtEvenIndexes(numbers, startIndex, endIndex - 1) + numbers[endIndex];
            } else {
                return computeSumAtEvenIndexes(numbers, startIndex, endIndex - 1);
            }
        }
    }

    public static int countDivisibleBy3(int[] numbers, int startIndex, int endIndex) {
        if (startIndex == endIndex) {
            if (numbers[startIndex] % 3 == 0) {
                return +2;
            } else {
                return 1;
            }
        } else {
            if (numbers[endIndex] == 0) {
                return countDivisibleBy3(numbers, startIndex, endIndex - 1);
            }
            if (numbers[endIndex] % 3 == 0) {
                return countDivisibleBy3(numbers, startIndex, endIndex - 1) + 1;
            } else {
                return countDivisibleBy3(numbers, startIndex, endIndex - 1);
            }
        }
    }

    private static int findMaxOfLessThanFirst(int[] numbers, int startIndex, int endIndex, int firstNumber) {
        if (startIndex == endIndex) {
            if (numbers[endIndex] <= firstNumber)
                return numbers[startIndex];
        }
        int max = findMaxOfLessThanFirst(numbers, startIndex, endIndex - 1, firstNumber);
        if (max >= numbers[endIndex] && max <= firstNumber) {
            return max;
        }
        return numbers[endIndex];
    }
}

我确定我在这里遗漏了一些非常基本的东西。我刚开始学习递归的概念。所以,请温柔一点。

【问题讨论】:

  • 这个问题之前有人问过,虽然它没有完整的答案stackoverflow.com/questions/43148782/… 但它似乎是一个家庭作业问题,“提问者”没有给它足够的时间。
  • 只将代码放在您遇到问题的地方,以便其他人易于阅读。
  • 我想今天有人问了完全相同的问题。
  • 在决定发帖之前,我尝试了很多思考。我的错。不知道还有其他人问同样的问题。

标签: java arrays recursion stack-overflow


【解决方案1】:

您遇到了无限递归(这通常是在递归程序中获得StackOverflowError 的情况)。您尝试使用此代码来停止递归:

    if (startIndex == endIndex) {
        if (numbers[endIndex] <= firstNumber)
            return numbers[startIndex];
    }

但是,当startIndex == endIndex(你唯一的机会),如果numbers[endIndex] &gt; firstNumber,这不会停止递归,所以它会继续——不是无限的,“只有”直到你碰到StackOverflowError

【讨论】:

  • 好的。这就说得通了。但是,现在,在某些测试用例中,该方法似乎无法正常工作。输入:-31、-31、-31、-34、-34、-31、0、-31、-34、-34、-31。它返回最大值为0。当第一个数字不为负时,它似乎可以正常工作。
  • 为了简单起见,我尝试输入 -1, -4, 0。在我输入 0 后,您的程序不接受任何输入。不过,它仍然会检查数组中的所有 100 个数字。因此,您的递归方法会查看更短的子数组,直到 startIndex 和 endIndex 都为 1。此时它返回 -4。由于-4不大于后面的元素0,所以你的方法返回numbers[endIndex],也就是0,剩下的出路。
【解决方案2】:

您需要做的就是删除第一个if 中嵌套的if 条件。这是多余的,因为startIndexendIndex 是相同的。下面应该工作:

private static int findMaxOfLessThanFirst(int[] numbers, int startIndex, int endIndex, int firstNumber) {
    if (startIndex == endIndex) {
        return numbers[startIndex];
    }
    int max = findMaxOfLessThanFirst(numbers, startIndex, endIndex - 1, firstNumber);
    if (max >= numbers[endIndex] && max <= firstNumber) {
        return max;
    }
    return numbers[endIndex];
}

【讨论】:

    【解决方案3】:

    您缺少else 分支。哪里有if,哪里就有else,我用这个作为编程的规则。在某些情况下else 可能没用,在这种情况下我会在else 中添加一些日志信息。

     private static int findMaxOfLessThanFirst(int[] numbers, int startIndex, int endIndex, int firstNumber) {
        if (startIndex == endIndex) {
            if (numbers[endIndex] <= firstNumber)
                return numbers[startIndex];          
            else return Integer.MIN_VALUE;
        }
        int max = findMaxOfLessThanFirst(numbers, startIndex, endIndex - 1, firstNumber);
        if (max >= numbers[endIndex] && max<=firstNumber) {
            return max;
        }
        return numbers[endIndex];
    }
    

    【讨论】:

    • 认为你做对了。但是,仅代码答案不是很有用。也许您会想解释一下您的代码解决了什么问题以及它是如何解决的?
    • 是的,你是对的。我只是通过思考差异而不是阅读解释来思考精益求精;)
    猜你喜欢
    • 1970-01-01
    • 2020-07-13
    • 1970-01-01
    • 2012-11-06
    • 1970-01-01
    • 2015-04-04
    • 2017-01-20
    • 2018-12-02
    • 2017-09-06
    相关资源
    最近更新 更多