“计算你减去 3 的次数”算法需要 theta(|input|) 步骤。您可能会争辩说 theta(|input|) 对于 32 位整数很好,在这种情况下,为什么要进行任何编程?只需使用查找表。但是,有更快的方法可用于更大的输入。
您可以对商执行二进制搜索,通过将 q+q+q 与输入进行比较来测试候选商 q 是太大还是太小。二分查找需要 theta(log |input|) 时间。
二进制搜索使用除以 2,这可以通过移位运算符而不是 / 来完成,或者如果移位运算符太接近除法,您可以自己在位数组上实现这一点。
通过尝试 (n>>2) + ( n>>4) + (n>>6) + ... 但是这会产生错误的答案 n=3,6,7,9, 11, 12, 13, 14, 15, 18, ... 它是对于 n=15,30,31,39,.. 关闭 2。一般来说,这是关闭 O(log n)。对于 n 个非负数,
(n>>2) + (n>>4) + (n>>6) + ... = (n-wt4(n))/3
其中 wt4(n) 是 n 的基数 4 位的总和,右侧的 / 是精确的,而不是整数除法。我们可以通过将 wt4(n)/3 添加到 (n>>2)+(n>>4)+(n>>6)+ 来计算 n/3... 我们可以计算 n 的基数 4 位,因此wt4(n) 只使用加法和右移。
int oneThirdOf(int n){
if (0<=n && n<3)
return 0;
if (n==3)
return 1;
return sum(n) + oneThirdOf(wt4(n));
}
// Compute (n>>2) + (n>>4) + (n>>6) + ... recursively.
int sum(int n){
if (n<4)
return 0;
return (n>>2) + sum(n>>2);
}
// Compute the sum of the digits of n base 4 recursively.
int wt4(int n){
if (n<4)
return n;
int fourth = n>>2;
int lastDigit = n-fourth-fourth-fourth-fourth;
return wt4(fourth) + lastDigit;
}
这也需要 theta(日志输入)步骤。