【问题标题】:Subset Generator gives out java heap space error子集生成器给出 java 堆空间错误
【发布时间】:2015-05-15 11:49:37
【问题描述】:

这是我在运行测试程序类时收到的错误。我一直在查看代码指向的位置,但我看不出问题出在哪里。它一直说我也没有Java堆空间,不确定那是什么。我也不确定我的递归 getsubset() 方法是否正常工作,因为我什至无法编译我的测试器类。如果我的代码中有任何其他错误,请随时指出。谢谢!

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
        at java.util.Arrays.copyOfRange(Arrays.java:3209)
        at java.lang.String.<init>(String.java:215)
        at java.lang.StringBuilder.toString(StringBuilder.java:430)
        at SubsetGenerator.getSubsets(SubsetGenerator.java:68)
        at SubsetGenerator.getSubsets(SubsetGenerator.java:64)
        at SubsetGeneratorTester2.main(SubsetGeneratorTester2.java:23)
Press any key to continue...





 import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
   Prints subsets of String
*/

public class SubsetGenerator
{
    private String word="";

    private ArrayList<String> subsets;

    /**
        Constructs a word to generate subsets from
        @param text input by user
    */
    public SubsetGenerator(String textinput)
    {
        word=textinput;
        subsets = new ArrayList<String>();
    }



    /**
        retrieves word
        @return the word
    */
    public String getWord()
    {
        return word;
    }




    /**
        get subsets
        @return subset arraylist
    */
    public ArrayList<String> getSubsets()
    {
        if(word.length() == 1)
        {
            subsets.add(word);
            return subsets;
        }
        else
        {

            String removed = word.substring(0,1);
            word = word.substring(1);

            getSubsets();

            for (int i = 0; i < subsets.size(); i++)
            {
                String temp = removed + subsets.get(i);
                subsets.add(temp);
            }
            subsets.add(removed);
            return subsets;
        }
    }

    //sort subsets
    public void sortSubsets()
    {
        Collections.sort(subsets);
    }
}



import java.util.Collections;
import java.util.ArrayList;
import java.util.List;

/**
   This program tests the subset generator.
*/
public class SubsetGeneratorTester2
{
   public static void main(String[] args)
   {
      SubsetGenerator generator = new SubsetGenerator("rum");

      List<String> subsets = generator.getSubsets();
      // Sort the result for checking
      Collections.sort(subsets);
      System.out.println(subsets);
      System.out.println("Expected: [, m, r, rm, ru, rum, u, um]");
   }
}

【问题讨论】:

  • 那个循环看起来是无限的。如果它不为空,则添加一个元素以增加大小。然后由于元素为空,i+1 永远不能大于或等于新大小。这将很容易耗尽堆。

标签: java recursion arraylist subset space


【解决方案1】:

我会给你另一个比你的更清楚的解决方案。首先从单词中截取一个字符。然后使用该字符连接其余部分。最后递归调用getSubsets()。如果word.length 为零,则到达底部并返回。

   public ArrayList<String> getSubsets(){
         if(word.length()==0){
             subsets.add("");
             return subsets;
         }
         else{
             String removed=word.substring(0,1);
             word=word.substring(1);
             subsets.add(removed);

             for(int i=0;i<word.length();i++){
                String temp=removed+word.substring(0,i+1);
                subsets.add(temp);
             }
         }

         getSubsets();
         return subsets;
   }

这是我的回答:

root@MQ-PC:/home/java/algorithm# java SubsetGenerator 
[r, ru, rum, u, um, m, ]

【讨论】:

    【解决方案2】:

    问题似乎与循环有关。如果它不为空,则添加一个元素以增加大小。然后由于一个元素是空的, i+1 永远不能大于或等于新的大小。这将很容易耗尽堆。但是,这会在空字符串上失败,并立即出现运行时错误。

    我可以确认循环是罪魁祸首。通过简单地将索引移出循环来解决此问题。这样它就不会随着元素的添加而更新。

            int size = subsets.size();
            for (int i = 0; i < size; i++)
            {
                String temp = removed + subsets.get(i);
                subsets.add(temp);
            }
    

    但是,还有另一个问题。

    你的方法导致了集合:

    [m, r, rm, ru, rum, u, um]
    

    这很容易改变,因为你的基本情况是错误的。我也不想修改太多代码(但有更好的方法!)

    在您的示例中,空字符串永远不会起作用,但它应该在逻辑上起作用。我的处理方式如下(伪代码):

    List subset(String str):
        if(length == 0):
            return [""];
        x = subset(str.substring(1));
        result = [];
        for s in x:
            result += [s, str.charAt(0) + s];
        return result;
    

    这当然是伪代码(实际上接近 python)。我不想全部放弃,但基本优点是了解如何实现这些。

    需要注意的重要一点是,对于每个元素,我们将 2 个字符串添加到列表中。一个包含当前字符串的第一个字符,一个不包含当前字符串的第一个字符。

    考虑一些基本情况:

    subset("")   -> [""]
    subset("a")  -> ["", "a"] 
    subset("ab") -> ["", "a", "b", "ab"]
    

    希望你能看到模式。对于每个字符串,我们添加一个带字符的字符串,一个不带字符的字符串。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-09-15
      • 1970-01-01
      • 2023-04-07
      • 1970-01-01
      • 2011-10-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多