簡體   English   中英

將算法從o(n)轉換為o(1)

[英]Convert algorithm from o(n) to o(1)

基本上我想是一個數n是整除ba (數)次,然后找到a (數),除n通過ba (數)次。

那是,

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=8b=5因為在右邊沒有零。手側。

除非在b為2的冪的情況下可以使用按位邏輯推論出答案,否則這不一定會提高速度,但是它為您提供了另一種方式以數字方式而不是數字方式查看問題通過算術。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM