如何找到没有" 111"的零和0的序列数。

时间:2013-12-06 13:38:00

标签: c++ algorithm dynamic

我有一个问题: 我有一个N(N <= 40)。 N是0和1的序列长度。如何找到零和序列的数量,其中没有三个“1”在一起?

实施例: N = 3,答案= 7

0 0 0
0 0 1
0 1 0
0 1 1
1 0 0
1 0 1
1 1 0

4 个答案:

答案 0 :(得分:1)

这是使用递归函数的解决方案:

(PHP代码在这里,但它非常简单)

$seq = '';

function tree ($node, $flag, $seq)
{
if ($flag == 3) { return 0; }

if ($node == 0) { echo $seq, ' '; return 0;}

$seq1 = $seq.'1';
$seq2 = $seq.'0';

tree($node-1, $flag+1, $seq1);
tree($node-1, 0, $seq2);

}

tree(8, 0, $seq);

我使用树来浏览所有可能的序列,并使用一个标志来检查连续多少个。

如果连续有两个1,则该标志达到3,并且该分支的功能停止。

如果我们到达树的叶子(即$ node = 0),则显示序列,函数结束。

否则,该函数将从当前节点开始探索两个子树。

void tree ( int node, int flag, std::string seq)
{
    std::string seq1 = seq;        
    std::string seq2 = seq;

    if(flag ==3) { return; }
    if(node ==0) { printf("%s\n",seq.c_str()); return;}

    seq1 += '1';
    seq2 += '0';

    tree(node-1, flag+1, seq1);
    tree(node-1, 0, seq2);

}

答案 1 :(得分:0)

这是一个dp问题。我将以某种方式解释解决方案,以便很容易修改它来计算没有序列的序列数 0 a 1 a 2 in(其中 i 是任意二进制值)。

我将使用4个辅助变量,每个辅助变量计数一个有效的给定长度的序列,并分别以00,01,10和11结束。将那些命名为c00,c01,c10,c11。很明显,对于长度N = 2,这些数字都是1:

int c00 = 1;
int c01 = 1;
int c10 = 1;
int c11 = 1;

现在假设我们已将序列计数到给定长度k,我们按以下方式计算长度为k + 1的四个组中的序列:

int new_c00 = c10 + c00; 
int new_c01 = c10 + c00;
int new_c10 = c01 + c11;
int new_c11 = c01;

上面的逻辑非常简单 - 如果我们将0附加到k结尾的0 01 0结尾的序列,我们最终会得到一个新的序列k + 1,以0 0结尾,依此类推上面的其他等式。

请注意,c11未添加到以1 1结尾且长度为k + 1的序列数中。这是因为如果我们将1追加到以1 1结尾的序列,我们将得到一个无效的序列(以1 1 1结尾)。

以下是针对您案例的完整解决方案:

int c00 = 1;
int c01 = 1;
int c10 = 1;
int c11 = 1;
for (int i = 0; i < n - 2; ++i) {
  int new_c00 = c10 + c00; 
  int new_c01 = c10 + c00;
  int new_c10 = c01 + c11;
  int new_c11 = c01;
  c00 = new_c00;
  c01 = new_c01;
  c10 = new_c10;
  c11 = new_c11;
}
// total valid sequences of length n
int result = c00 + c01 + c10 + c11; 
cout << result << endl;

当N

答案 2 :(得分:0)

您可以为此语言的(非空)字符串编写语法。它的设计使得每个字符串只出现一次。

S := 0 | 1 | 11 | 10 | 110 | 0S | 10S | 110S

设a_i为S中长度为i的字符串总数。

首先,查看语法规则两侧长度为1的字符串数。根据定义,S中有a_1处理左侧。

a_1 = 2

对于a_2,在右侧,我们立即得到两个长度为2(11和10)的字符串,再加上0S规则(00和01)中的另外两个字符串。这给了我们:

a_2 = 2 + a_1 = 4

同样,对于a_3,我们得到:

a_3 = 1 + a_2 + a_1 = 7

(到目前为止,我们已经为字符串长度为3的情况找到了正确的解决方案7。)

对于i&gt; 3,考虑两边长度为i的字符串数。

a_i = a_{i-1} + a_{i-2} + a_{i-3}

现在我们可以使用我们的复发了。快速检查a_4 ...

a_4 = a_1 + a_2 + a_3 = 2 + 4 + 7 = 13.

有16个长度为4的字符串和3个包含111:1110,0111,1111的字符串。所以13看起来正确!

这是一般案例的Python中的一些代码,使用这种重复。

def strings_without_111(n):
    if n == 0: return 1
    a = [2, 4, 7]
    for _ in xrange(n - 1):
        a = [a[1], a[2], a[0] + a[1] + a[2]]
    return a[0]

答案 3 :(得分:0)

要查找N位的所有可能序列的数量很容易。它是2^N

要查找包含111的所有序列更难一点。

假设N=3然后Count = 1

111

假设N=4然后Count = 3

0111
1110
1111

假设N=5然后Count = 8

11100
11101
11110
11111
01110
01111
00111
10111

如果您编写简单的模拟程序,则会产生1 3 8 20 47 107 ...

减去2^n - count(n) = 2 4 7 13 24 44 81 149...

谷歌它给它OEIS序列,称为tribonacci数字。通过简单的递归方程求解:

a(n) = a(n - 1) + a(n - 2) + a(n - 3)