我有一个问题: 我有一个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
答案 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 0
或1 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)