子集生成器发出java堆空间错误

子集生成器发出java堆空间错误,java,recursion,arraylist,subset,space,Java,Recursion,Arraylist,Subset,Space,下面是我在运行tester类时收到的错误。我一直在看代码指向哪里,但我看不到问题在哪里。它一直说我也没有Java堆空间,不知道那是什么。我也不确定我的递归getsubset方法是否正常工作,因为我甚至不能编译我的tester类。如果我的代码中有任何其他错误,请随时指出。谢谢大家! Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at java.util.Arrays.copyOfRang

下面是我在运行tester类时收到的错误。我一直在看代码指向哪里,但我看不到问题在哪里。它一直说我也没有Java堆空间,不知道那是什么。我也不确定我的递归getsubset方法是否正常工作,因为我甚至不能编译我的tester类。如果我的代码中有任何其他错误,请随时指出。谢谢大家!

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不能大于或等于新的大小。这将很容易耗尽堆。但是,这在空字符串上失败,并立即出现运行时错误

我可以确认回路是罪魁祸首。只需将索引移出循环,即可修复此问题。这样,它就不会随着元素的添加而更新

        int size = subsets.size();
        for (int i = 0; i < size; i++)
        {
            String temp = removed + subsets.get(i);
            subsets.add(temp);
        }
这很容易改变,因为你的基本情况是错误的。我也不想修改太多的代码,但有一个更好的方法可以做到这一点

在您的示例中,不管空字符串在逻辑上如何,它都不会工作。我将以伪代码的方式处理此问题,如下所示:

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"]

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

我会给你另一个比你更清楚的解决方案。首先从单词中删除一个字符。然后使用该字符连接其余字符。最后递归调用getSubset。如果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;
   }

这个循环看起来是无限的。如果其不是空的,则添加一个元素以增加大小。因为元素是空的,所以i+1不能大于或等于新的大小。这将很容易耗尽堆。
   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, ]