[英]Convert algorithm from o(n) to o(1)
基本上我想是一个数n
是整除b
为a
(数)次,然后找到a
(数),除n
通过b
为a
(数)次。
那是,
count = 0;
while(n%b == 0)
n=n/b;
count = count + 1;
如何优化这一点,以便一步就能获得所有内容
您可以在已排序的“列表”上应用二进制搜索以找到等于1的最后一个元素,从而在O(log(a))
此操作。
该列表是隐喻的,通过简单的计算查询该列表中的每个元素都是即时计算的:
list[i] = 1 n % a^i == 0
0 otherwise
你可以先找到可能的范围内a
的使用exponention:
curr = b
tempA = 1
while n % curr == 0:
curr = curr * curr
tempA = tempA *2
然后,在范围[tempA/2, tempA]
上运行二进制搜索。 此范围的大小为(a/2)
,因此可以通过O(loga)
乘法来找到符号列表包含1
的最后一个“元素”。
代码+演示:
private static int specialBinarySearch(int n, int b, int aLow, int aHigh) {
if (aHigh == aLow) return aHigh;
int mid = (aHigh - aLow)/2 + aLow;
//pow method can be optimized to remember pre-calculated values and use them
int curr = (int)Math.round(Math.pow(b, mid));
if (n % curr == 0) { //2nd half, or found it:
if (n % (curr*b) != 0) return mid; //found it
return specialBinarySearch(n, b, mid+1, aHigh); //2nd half
}
else return specialBinarySearch(n, b, aLow, mid); //first half
}
public static int findA(int n, int b) {
int curr = b;
int tempA = 1;
while (n % curr == 0) {
curr = curr * curr;
tempA = tempA *2;
}
return specialBinarySearch(n, b, tempA/2, tempA);
}
public static void main(String args[]) {
System.out.println(findA(62,2)); //1
System.out.println(findA(1024,2)); //10
System.out.println(findA(1,2)); //0
System.out.println(findA(100,2)); //2
System.out.println(findA(6804,3)); //5
}
您无法在O(1)中解决此问题,但是如果您开始使用以b
为基数的数字系统,则有另一种方法可以解决此问题。
例如,如果我们有一个像154200这样的数字,并且b
是10,那么我们立即知道答案是2,因为我们可以简单地计算出右边有多少个零。
同样,在二进制中,如果b
为2,则只需用二进制表示就可以计算出右侧有多少个零。
如果b
为5,我们必须使用奇数基数5表示,其中像8这样的数字表示为13。同样,我们知道a
的答案是零,即n=8
和b=5
因为在右边没有零。手侧。
除非在b
为2的幂的情况下可以使用按位逻辑推论出答案,否则这不一定会提高速度,但是它为您提供了另一种方式以数字方式而不是数字方式查看问题通过算术。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.