[英]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.