【问题标题】:why does this code gives stackoverflow error when word length is beyond 4?为什么当字长超过 4 时这段代码会给出 stackoverflow 错误?
【发布时间】:2019-10-05 15:23:08
【问题描述】:

我已经编写了一个代码来生成一个单词的所有可能的字母组合,而不会重复任何字母或任何特定的单词。代码如下

static boolean redcheck(int array[])// checks if letters are repeated
{
    boolean check=true;
    for(int i=0;i<array.length-1;i++)
    {
        for(int j=i+1;j<array.length;j++)
        {
            if(array[i]==array[j])
            {
                check=false;
                break;
            }
        }
    }
    return check;
}

static void repeat(char arr2[],int arr1[],int p)// creates and prints the word
{
    if(redcheck(arr1))
    {
        for(int i=0;i<p;i++)
            System.out.print(arr2[arr1[i]]);
        for(int i=0;i<p;i++)
            System.out.print(arr1[i]);
        System.out.println();
    }
    arr1[p-1]+=1;
    for(int ini=p-1;ini>0;ini--)
    {  
        if(arr1[ini]>p-1)
        {
            arr1[ini-1]+=1;
            arr1[ini]=0;  
        }
    }
    if(arr1[0]>p-1)
        return;

    repeat(arr2,arr1,p);
}

public static void main()
{
    Scanner sc=new Scanner(System.in);
    System.out.println("enter word");
    String a=sc.nextLine();
    int num=a.length();
    char arr[]=new char[num];
    for(int c=0;c<a.length();c++)
        arr[c]=a.charAt(c);

    int arr1[]=new int[num];
    for(int i:arr1)
        arr1[i]=0;
    repeat(arr,arr1,num);

}

代码可以正常工作,直到长度为 4 的任何单词,但是当长度超过 4 时,它会引发堆栈溢出错误。经过一番检查,造成问题的代码的主要部分是打印部分本身,即

for(int i=0;i<p;i++)
            System.out.print(arr2[arr1[i]]);

我真的找不到哪里出错了。上面提到的下面的 print 语句,按照它们将被打印的顺序打印单词的索引,并且不会给出任何错误。 我正在使用 bluej 编辑器,看起来我有 512MB 的堆栈内存。 请帮助。在此先感谢。

编辑:错误代码是 java.lang.StackOverflow错误: 空

【问题讨论】:

  • 我不清楚代码是如何工作的,但除非arr1[0] &gt; p - 1,否则你总是在递归。你的意思是递归那么多吗?请注意,您只需使用 do/while 循环即可轻松避免递归。
  • 包含确切的错误信息会有所帮助
  • @JonSkeet 字母的重新排列方式可以与人们使用的点击计数器进行比较。假设你有一个只有数字 0、1、2 的数字系统。现在最小的是000,然后你加1得到001,然后是002。当002到来时,下一个数字通常应该是003,但不包括3,因此重置个位,下一个位置加1 .给010。就像最后一个应该是222,因此当它增加1时,逻辑导致300被制作,但由于3不包括在内并且在最后一个位置,所以函数被终止
  • @P.Soutzikevich 它的 java.lang.StackOverflowError: null
  • @Crasshassin 不在 cmets 中。适当编辑您的问题

标签: java arrays recursion stack-overflow


【解决方案1】:

有 4 个字母(假设它们都不相同),这些字母有 4^4 = 256 种可能的组合。由于您的代码当前已设置,您将在返回一个值之前至少递归 256 次,这将在您的堆栈上占用大量内存。如果您尝试扩大到 5 个字母(再次假设没有相同),您将有 5^5 = 3125 种可能的组合,等等...... 您得到的堆栈溢出错误是由于您递归的时间量。

我的建议: 将您的重复方法分成两部分:

static void printWord(char arr2[],int arr1[],int p) {
    if(redcheck(arr1))
    {
        for(int i=0;i<p;i++)
            System.out.print(arr2[arr1[i]]);
        for(int i=0;i<p;i++)
            System.out.print(arr1[i]);
        System.out.println();
    }
}

然后是你的重复方法:

static void repeat(char arr2[],int arr1[],int p)// creates and prints the word
{
    while(arr1[0] < p-1){
        printWord(char arr2[],int arr1[],int p);
        arr1[p-1]+=1; // your looping logic
        for(int ini=p-1;ini>0;ini--)
        {  
            if(arr1[ini]>p-1)
            {
                arr1[ini-1]+=1;
                arr1[ini]=0;  
            }
        }
    }
}

使其成为非递归将帮助您避免堆栈溢出错误。

其他建议: 在运行任何逻辑之前验证输入单词是否没有两个相同的字母,如果我输入单词“see”,您的代码将找不到任何组合,因为没有组合可以用字母创建三个字母的单词{'s','e','e'} 没有任何重复。 您的 redcheck 方法使用了太多变量:

static boolean redcheck(int array[])// checks if letters are repeated
{
    for(int i=0;i<array.length-1;i++)
    {
        for(int j=i+1;j<array.length;j++)
        {
            if(array[i]==array[j])
            {
                return false;
            }
        }
    }
    return true;
}

【讨论】:

  • 谢谢@michmich12。让我在这里说实话,我真的考虑过将程序分成几部分,并留下了这个想法,因为我认为它是微不足道的。但你知道吗,这确实有帮助。该代码现在可以处理 5 个字母的单词,但猜猜看,它不能处理 6 个字母的单词。正如您所指出的,似乎问题出在内存上,但是现在,代码不能再进一步划分了,所以现在看来​​ 5 是极限了!不过还是非常感谢你的回答!!
  • 没问题@Crasshassin。 6个字母返回什么样的错误?
  • @michmich12,至于 redcheck 方法和重复出现的字母,是的,程序可以很好地处理它们(是的,只有 5 个字母的单词!),因为你看到了, word 没有被直接使用,另一个数组实际上使每个字母都是唯一的,因为它们具有单独的数字格式索引。 red(dundancy)check 方法比较的是这个索引而不是字母本身,所以就逻辑而言,重复出现的字母没有问题,但内存问题仍然会困扰我!
  • 第 6 个字母与第 5 个字母给出的错误相同,即 java.lang.StackOverflowError: null
  • @michmich12 ,我忘了一件事。我从我的另一个代码开发了这段代码,它使用相同的逻辑但有不同的目的。该代码创建任意位数的二进制序列。这里的序列意味着像这样的升序。如果用户输入 3,它将打印 000,001,010,011,100,101,110,111。对于任何数字也是如此。在这个问题中的代码开始困扰我之后,我尝试测试这个二进制代码。似乎这个限制是 12 位数字。这是一个非常神秘有趣的方向!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-19
相关资源
最近更新 更多