一个人如何有效地产生所有相等数量的0和1的二进制序列?


10

二进制序列长度的只是一个有序序列使得每个要么是或。为了生成所有这样的二进制序列,可以按以下方式使用明显的二进制树结构:根为“空”,但是每个左子级对应于现有字符串的附加值,每个右子级对应于。现在,每个二进制序列只是一条长度为的路径,该路径从根开始并在叶处终止。x 1x n x j 0 1 0 1 n + 1ñX1个XñXĴ01个01个ñ+1个

这是我的问题:

如果我们只想生成所有长度二进制字符串,它们恰好具有零和,我们可以做得更好吗?n n2ñññ

所谓“我们可以做得更好”,是指我们应该比笨拙的算法具有更低的复杂度,后者首先在上面构建整个树,然后尝试找到具有相等数量“左”和“右”边的路径。


您能找到一种方法来有效生成数字从1到所有严格递增的序列的方法吗?2 nñ2ñ
Cornelius Brand

我无法评论复杂性,但是我的幼稚算法会使用一种回溯方案来生成从一个角到对角线沿着正方形网格的边缘的走动。这意味着01和10最终位于同一位置(与您的树不同),但是通过回溯,我们知道了这个历史。
Hendrik 2013年1

需要说明的是,这是 -iterator的Java实现。ñķ
2013年

Answers:


6

显然有二进制字符串,长度。要遍历二进制,算法必须访问每个节点一次,即必须执行 步骤。 2 n 2 n i = 0 2 i = 2 2 n + 11 = O4 n4ñ2ñ

一世=02ñ2一世=22ñ+1个-1个=Ø4ñ

让我们考虑一个递归算法,该算法遍历您描述的树,但是在其途中计算一和零的数量,即,它只会遍历树的大部分。
但是,有多少个这样的具有 0和 1的二进制字符串?我们为长度的字符串选择 1,并在步骤2中使用斯特林公式: n n 2 n 2 nñññ2ñ

2ññ=2ññ2=4ñπñ1个+Ø1个/ñ

编辑
感谢Peter Shor的评论,我们还可以分析第二个算法所需的步数,该算法计算1和0。我从下面引用他的评论:

我们想找到所有正好为 0和 1的二进制序列。我们遍历二叉树,其中每个节点是一个最多 0和1的序列。我们不需要访问大于 0或大于 1的任何节点。我们需要访问多少个节点?有带有 0和 1的字符串。对所有求和得出。现在,我们需要以每个节点不变的平均成本访问这些节点中的每个节点。为此,我们可以先拜访每个左孩子,然后拜访每个右孩子。n 2 n n n i + jññ2ñññĴĴÑΣÑ= 0 ΣÑ Ĵ = 0 +Ĵ一世+Ĵ一世一世Ĵ一世Ĵñ一世=0ñĴ=0ñ一世+Ĵ一世=2ñ+2ñ+1个-1个

再次使用斯特林公式,我们得到 作为新算法的运行时间。

2ñ+2ñ+1个-1个=4ñ+1个1个ñ+1个1个+Ø1个/ñ-1个=Ø4ññ

您必须多加小心。大概在生成每个字符串之后,我们将在时间对其进行处理。因此,仅处理所有平衡的字符串就需要时间。如果优化的“愚蠢”生成算法确实为,那么切换到更智能的算法并没有太多收获,除了发现错误的机会。Ω 4 Ñ ΩñO4nΩ4ññØ4ñ
Yuval Filmus 2013年

@Yuval Filmus:“字符串处理”到底是什么意思?如果您要花费在输出上的时间肯定是,那么您还必须在“傻”算法的运行时间中考虑该因素,该时间就是。Θ(ñØ4ññ
tranitortor

2
我的观点是,如果您担心和之间的差异,那么至少必须声明正确的运行时间;不足以揭示两种算法之间的任何潜在差异。另外,您必须仔细分析提出的新算法,以确保这些“可忽略的”小因素不会使其比普通算法慢。4ñ4ñ/ñØ4ñ
Yuval Filmus 2013年

2
您如何只构建树的“好部分”而又不必包括“坏部分”?您需要包括从根到它们的路径上的树中所有不超过左子节点或右子节点的节点。这可行,但是您需要一个额外的参数来证明它可行。具体来说,您需要使用公式。ññ一世=0ñĴ=0ñ一世+Ĵ一世=2ñ+2ñ+1个-1个
Peter Shor 2013年

2
我们想找到所有正好为 0和 1的二进制序列。我们遍历二叉树,其中每个节点是一个最多 0和1的序列。我们不需要访问大于 0或大于 1的任何节点。我们需要访问多少个节点?有带有 0和 1的字符串。将所有得出。现在,我们需要以每个节点不变的平均成本访问这些节点中的每个节点。为此,我们可以先拜访每个左孩子,然后拜访每个右孩子。ññ2ñññ一世+Ĵ一世一世Ĵ一世Ĵñ一世=0ñĴ=0ñ一世+Ĵ一世=2ñ+2ñ+1个-1个
彼得·索尔

2

也许我很胖,但最初的问题要求一种生成长度为2n的所有“平衡”二进制序列的方法,该方法比遍历长度为2n 的所有二进制序列的树并仅输出平衡的树的效率更高。那为什么要只用一棵树呢?

以下是生成所有此类序列的递归算法的伪代码(关键字“ yield”将序列发送至输出):

function all-balanced(n) {
  all-specified( "", n, n );
};

function all-specified( currentString, zeroes, ones ) {

  if (zeroes == 0) {
    for i = 0 to ones {
      currentString += "1";
    };
    yield currentString;
    return;
  };

  if (ones == 0) {
    for i = 0 to zeroes {
      currentString += "0";
    };
    yield currentString;
    return;
  };

  all-specified( currentString+"0", zeroes-1, ones );
  all-specified( currentString+"1", zeroes, ones-1 );
  return;
};

如果我误会了什么,请告诉我,但是在我看来,这是对实际提出的问题的最有效答案,该问题从未指定使用树。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.