C 生成具有重复数字的所有组合

C 生成具有重复数字的所有组合,c,recursion,C,Recursion,我已经阅读了这个网站足够长的时间,知道不要隐瞒这是一个家庭作业。但我正在尝试编写一个代码,它可以生成一个只有0和1的字符串的所有可能组合。如果字符串的长度为n^2,则将有n个1,其余为0。长度总是一个完美的正方形。我是用C语言编写代码的,我一直尝试在嵌套循环中编写,但似乎可以用递归的方式更容易地完成,我只是不知道如何设置。任何提示或建议都将不胜感激。伪代码: myfun(pos,length, ones) if (length==0) pos='\0' #print, c

我已经阅读了这个网站足够长的时间,知道不要隐瞒这是一个家庭作业。但我正在尝试编写一个代码,它可以生成一个只有0和1的字符串的所有可能组合。如果字符串的长度为n^2,则将有n个1,其余为0。长度总是一个完美的正方形。我是用C语言编写代码的,我一直尝试在嵌套循环中编写,但似乎可以用递归的方式更容易地完成,我只是不知道如何设置。任何提示或建议都将不胜感激。

伪代码:

myfun(pos,length, ones)
  if (length==0)
     pos='\0'
     #print, collect, whatever...
     return
  if (length>ones)
    pos='0'
    myfun(pos+1,length-1, ones)
  pos='1'
  myfun(pos+1, length-1, ones-1)

task(n)
  #allocate n^2 buffer
  myfun(buffer, n*n, n)

我不确定这个问题是否适合递归。在C和大多数语言中,每次调用函数时,都会创建一个堆栈帧,并使用几个处理器周期和一块堆栈内存。此问题的任何递归解决方案都将创建n^2个堆栈帧,即使递归本身只添加了一位信息

下面概述了一个非常糟糕的解决方案。它没有做什么:

利用n始终是完美正方形这一事实。 以非常智能的方式使用内存 释放它使用的任何内存 甚至可能不起作用; …但它可能会让你了解基本模式

void foo(int zeros_left, int length_left, char *s)
{
    if (length_left == 0)
        printf("%s\n", s);
    else
    {
        if (zeros_left > 0)
        {
            char *next = malloc(strlen(s) + 2);
            strcpy(next, s);
            strcat(next, "0");
            foo(zeros_left - 1, length_left - 1, next);
        }

        if (zeros_left != length_left)
        {
            char *next = malloc(strlen(s) + 2);
            strcpy(next, s);
            strcat(next, "1");
            foo(zeros_left, length_left - 1, next);
        }
    }
}

递归建模问题的关键是将问题的较大版本分解为一个简单的计算,再结合同一问题的较小版本,以及终止递归的一个小案例

在这种情况下,问题是:

对于非负M和N,输出长度为M且正好包含N 1s的所有字符串。 您可以将其分解为:

如果M=0,则输出空字符串;否则 输出长度为M-1的所有字符串,这些字符串正好包含N 1s,并在每个字符串前面加上0;和 如果N>0,则输出长度为M-1且正好包含N-1个1s的所有字符串,并在每个字符串前面加上1。
这里,M=0是终止递归的简单情况。将上述内容转换为代码相当简单。

然后你还应该知道你必须将其标记为家庭作业。你应该发布到目前为止为你的工作显示的代码。在这种情况下,我假设缓冲区的类型为char*。但是,您将其作为pos接收,它看起来被视为int。“pos”是否指向字符串中的特定元素?内存泄漏问题似乎是最大的问题。你不能改为重新定位字符串吗?不是所有地方,如果你在零的情况下重新定位字符串,那么它就不能在一个情况下再次重新定位。理论上,您可以使用realloc,但是有一种非常明显的方法可以释放上述解决方案中的所有malloc内存,而不会影响程序的正确性。