我怎样才能避免java.lang.StackOverflowError:null?

时间:2016-09-28 10:46:29

标签: java collatz

我试图自己学习Java 通常我有足够的资源和良好的网站,像这些, 但现在我只想知道我错在哪里。

所以这个问题的措辞是:

  

为正集合定义以下迭代序列   整数:

     

n→n / 2(n为偶数)n→3n + 1(n为奇数)

     

使用上面的规则并从13开始,我们生成以下内容   序列:

     

13→40→20→10→5→16→8→4→2→1可以看出这一点   序列(从13开始,在1结束)包含10个术语。   虽然尚未证实(Collat​​z问题),但人们认为   所有起始数字都以1结束。

     

哪个起始编号低于一百万,产生最长的链?

     

注意:链条启动后,允许条款高于1   万美元。

我一直得到这些java.lang.StackOverflowError,请有人帮帮我。 我的代码:

import java.util.HashMap;

public class Euler
{
    HashMap<Integer,Integer> check;
    int result;

    public Euler()
    {
        check = new HashMap<Integer,Integer>();     
    }

    public int search(int number)
    {

        int startingNumber = number;

        while (check.get(number)==null && number!=1){

            if (number%2==0){
                number = number / 2;
                result = search(number);
                result++;               
            }

            else {
                number = (3*number)+1;
                result = search(number);
                result++;
            }
        }

        if (check.get(startingNumber)!=null){
            result=result+check.get(number);
            check.put(startingNumber,result);

        }
        else{
            check.put(startingNumber,result);
        }

        return result;
    }

    public int test()
    {
        int temp = 0;
        int highest=0;
        int get = 0;
        for (int i=1000001;i>1;i--){
            result = 0;
            temp = search(i);
            if(temp>highest){
                highest=temp;
                get = i;
            }
            System.out.println(i);
        }

        return get;
    }


}

编辑:

public class Euler
{
   public Euler()
    {
    }

    public int quickSearch(int numb)
    {
        int steps = 0;
        while (numb != 1) {
            if (numb % 2 == 0) {
                numb /= 2;
            }
            else {
                numb = 3 * numb + 1;
            }
            steps++;
        }
        return steps;
    }


    public int test()
    {
        int temp = 0;
        int highest=0;
        int get = 0;
        for (int i=1;i<1000001;i=i+2){

            temp = quickSearch(i);
            if(temp>highest){
                highest=temp;
                get = i;
            }
            System.out.println(i);

        }

        return get;
    }
}

EDIT2: 因此在EDIT版本代码中,我从机器上冻结了,但是当我将int更改为long时,它工作得很好,虽然我理解使用一些Map存储值,你可以更快地找到它。谢谢大家!!

3 个答案:

答案 0 :(得分:0)

问题是,你有太多的递归调用。对此最好的解决方案是使代码迭代。只需重新编写while循环,首先检查是否已找到该号码,如果是,则返回获取该号码所需步骤的总和,然后从该号码获取1。否则只需更新下一步的数字,再次运行循环。与此同时,您只需要跟踪您获取已知数字所需的步骤。

就个人而言,我会完全删除HashMap并只有一个简单的while循环:

int steps = 0;
while (number != 1) {
    if (number % 2 == 0) number /= 2;
    else number = 3 * number + 1
    steps++;
}

编辑:如果你想添加HashMap来存储找到的值,你可以这样做(我假设你之前定义了一个名为HashMap<Long, Integer>的{​​{1}}:

foundNumbers

答案 1 :(得分:0)

虽然递归代码在很多情况下很容易和紧凑但是有可能堆栈溢出,特别是如果递归链的长度未知。

您的案例很简单,可以通过迭代轻松解决。因此,尝试使用迭代模型而不是递归模型。

答案 2 :(得分:-1)

问题在于:

public int search(int number)
{

    int startingNumber = number;

    while (check.get(number)==null && number!=1){

        if (number%2==0){
            number = number / 2;
            result = search(number);
            result++;               
        }

        else {
            number = (3*number)+1;
            result = search(number);
            result++;
        }
    }

    if (check.get(startingNumber)!=null){
        result=result+check.get(number);
        check.put(startingNumber,result);

    }
    else{
        check.put(startingNumber,result);
    }

    return result;
}

您递归调用search(int)并导致堆叠。