(方便测试)
反例(针对 C 版本):{8, 33, 27, 30, 9, 2, 35, 7, 26, 32, 2, 23, 0, 13, 1, 6, 31, 3, 28, 4, 5、18、12、2、9、14、17、21、19、22、15、20、24、11、10、16、25}。这里n=0,m=35。此序列未命中34
并有两个2
.
它在时间上是 O(m),在空间上是 O(1)。
在时间 O(n) 和空间 O(1) 中很容易检测到超出范围的值,因此测试集中在范围内(意味着所有值都在有效范围内[n, n+m)
)序列。否则{1, 34}
是一个反例(对于 C 版本,sizeof(int)==4,数字的标准二进制表示)。
C 和 Ruby 版本之间的主要区别:
<<
由于 sizeof(int) 有限,运算符将旋转 C 中的值,但在 Ruby 中,数字会增长以适应结果,例如,
红宝石:1 << 100 # -> 1267650600228229401496703205376
C:int n = 100; 1 << n // -> 16
在 Ruby 中:check_index ^= 1 << i;
相当于check_index.setbit(i)
. 在 C++ 中可以实现相同的效果:vector<bool> v(m); v[i] = true;
bool isperm_fredric(int m; int a[m], int m, int n)
{
/**
O(m) in time (single pass), O(1) in space,
no restriction on n,
?overflow?
a[] may be readonly
*/
int check_index = 0;
int check_value = 0;
int min = a[0];
for (int i = 0; i < m; ++i) {
check_index ^= 1 << i;
check_value ^= 1 << (a[i] - n); //
if (a[i] < min)
min = a[i];
}
check_index <<= min - n; // min and n may differ e.g.,
// {1, 1}: min=1, but n may be 0.
return check_index == check_value;
}
上述函数的值已针对以下代码进行了测试:
bool *seen_isperm_trusted = NULL;
bool isperm_trusted(int m; int a[m], int m, int n)
{
/** O(m) in time, O(m) in space */
for (int i = 0; i < m; ++i) // could be memset(s_i_t, 0, m*sizeof(*s_i_t));
seen_isperm_trusted[i] = false;
for (int i = 0; i < m; ++i) {
if (a[i] < n or a[i] >= n + m)
return false; // out of range
if (seen_isperm_trusted[a[i]-n])
return false; // duplicates
else
seen_isperm_trusted[a[i]-n] = true;
}
return true; // a[] is a permutation of the range: [n, n+m)
}
输入数组通过以下方式生成:
void backtrack(int m; int a[m], int m, int nitems)
{
/** generate all permutations with repetition for the range [0, m) */
if (nitems == m) {
(void)test_array(a, nitems, 0); // {0, 0}, {0, 1}, {1, 0}, {1, 1}
}
else for (int i = 0; i < m; ++i) {
a[nitems] = i;
backtrack(a, m, nitems + 1);
}
}