将算法从o(n)转换为o(1)

时间:2015-05-16 09:55:54

标签: java c++ algorithm optimization division

基本上我想要的是,如果n b可以a整除a(计数)次,那么找n(计数),并除以b a count = 0; while(n%b == 0) n=n/b; count = count + 1; 次({计数}次。{/ p>

即,

func widgetPerformUpdateWithCompletionHandler(completionHandler: ((NCUpdateResult) -> Void)!) {

    self.preferredContentSize = self.tableView.contentSize
    var effectView = UIVisualEffectView(effect: UIVibrancyEffect.notificationCenterVibrancyEffect())
    effectView.frame = self.view.bounds
    self.view = effectView
    self.view.tintColor = UIColor.clearColor()
}

如何优化这一点,以便一步到位就可以获得所有内容

2 个答案:

答案 0 :(得分:4)

您可以通过在已排序的"列表中应用二进制搜索在O(log(a))中执行此操作。找到等于1的最后一个元素。

该列表是隐喻的,当通过简单的计算查询时,其中的每个元素都是动态计算的:

list[i] = 1      n % a^i == 0
          0      otherwise

您可以先使用exponention找到可能a的范围:

curr = b
tempA = 1
while n % curr == 0:
    curr = curr  * curr
    tempA = tempA *2

然后,在[tempA/2, tempA]范围内运行二进制搜索。此范围的大小为(a/2),因此找到最后一个"元素"符号列表保存1 - 在O(loga)次乘法中完成。

代码+演示:

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

}

答案 1 :(得分:0)

你无法在O(1)中解决这个问题,但如果你开始使用以b为基础的数字系统,则会遇到另一种解决此问题的方法。

例如,如果我们有一个像154200这样的数字,并且b是10,我们立即知道答案是2,因为我们可以简单地计算右边有多少个零。

同样,在二进制文件中,如果b为2,则只需计算右侧有多少个带有二进制表示的零。

如果b为5,我们必须使用奇数基数5表示,其中8之类的数字表示为13.再次,我们知道a的答案为零是{{1} }和n=8因为右侧没有零。

除非b=5是2的幂,你可以使用按位逻辑来推断答案,但这并不一定会给你提速,但它会给你一种不同的方式来看待这个问题通过数字而不是通过算术进行词汇化。