如何检查整数是否为3的幂?

时间:2009-11-26 15:27:06

标签: algorithm math

我看到了this question,并提出了这个想法。

25 个答案:

答案 0 :(得分:78)

while (n % 3 == 0) {
    n /= 3;
}
return n == 1;

注意1是第3的第0个力量。

编辑:您还需要在循环前检查零,因为循环不会因n = 0而终止(感谢Bruno Rothgiesser)。

答案 1 :(得分:77)

对于有限大小的整数(例如32位整数)存在恒定时间(非常快)的方法。

请注意,对于幂为3的整数N,以下情况属实:

  1. 对于权力为3的任何M <= NM除以N
  2. 对于任何不是权力3的M <= NM不会划分N
  3. 适合32位的3的最大功率是34867844013^20)。这给出了以下代码:

    bool isPower3(std::uint32_t value) {
        return value != 0 && 3486784401u % value == 0;
    }
    

    类似地,对于带符号的32位,它是11622614673^19):

    bool isPower3(std::int32_t value) {
        return value > 0 && 1162261467 % value == 0;
    }
    

    一般来说,幻数是:

    3^floor(log_3 MAX) == pow(3, floor(log(MAX) / log(3)))

    小心浮点舍入误差,使用像Wolfram Alpha这样的数学计算器来计算常数。例如,对于2^63-1(signed int64),C ++和Java都提供4052555153018976256,但正确的值为4052555153018976267

答案 2 :(得分:42)

我发现自己稍微认为如果用'整数'表示'签名的32位整数',那么(伪代码)

return (n == 1) 
    or (n == 3)
    or (n == 9)
    ... 
    or (n == 1162261467) 

有一定的美观(最后一个数字是3 ^ 19,所以没有荒谬的案例数)。即使对于无符号的64位整数,仍然只有41个案例(感谢@Alexandru指出我的大脑滑动)。当然,对于任意精度算术来说也是不可能的......

答案 3 :(得分:32)

我对此感到惊讶。 每个人似乎都错过了最快的算法。

以下算法平均速度更快 - 在某些情况下更快 - 比简单的while(n%3==0) n/=3;循环更快:

bool IsPowerOfThree(uint n)
{
  // Optimizing lines to handle the most common cases extremely quickly
  if(n%3 != 0) return n==1;
  if(n%9 != 0) return n==3;

  // General algorithm - works for any uint
  uint r;
  n = Math.DivRem(n, 59049, out r); if(n!=0 && r!=0) return false;
  n = Math.DivRem(n+r, 243, out r); if(n!=0 && r!=0) return false;
  n = Math.DivRem(n+r,  27, out r); if(n!=0 && r!=0) return false;
  n += r;
  return n==1 || n==3 || n==9;
}

代码中的数字常量为3 ^ 10,3 ^ 5和3 ^ 3.

效果计算

在现代CPU中,DivRem通常是单个指令,需要一个周期。在其他情况下,它扩展为div,然后是mul和add,这将更像是三个周期。通用算法的每一步看起来都很长,但它实际上只包含:DivRem, cmp, cmove, cmp, cand, cjmp, add。有很多可用的并行性,因此在典型的双向超标量处理器上,每个步骤可能会在大约4个时钟周期内执行,从而保证最差情况下的执行时间约为25个时钟周期。

如果输入值均匀分布在UInt32范围内,则以下是与此算法相关的概率:

  • 在第一个优化线之前或之前返回:66%的时间
  • 在第二条优化线之前或之前返回:89%的时间
  • 在第一个通用算法步骤中或之前返回:99.998%的时间
  • 在第二个通用算法步骤中或之前返回:99.99998%的时间
  • 在第三个通用算法步骤中或之前返回:99.999997%的时间

此算法优于简单while(n%3==0) n/=3循环,具有以下概率:

  • 在第一次迭代中返回:66%的时间
  • 在前两次迭代中返回:89%的时间
  • 在前三次迭代中返回:97%的时间
  • 在前四次迭代中返回:98.8%的时间
  • 在前五次迭代中返回:99.6%的时间......依此类推......
  • 在第一次十二次次迭代中返回:99.9998%的时间......超越......

更重要的是,这个算法可以更有效地处理三个(及其倍数)更多的中等和大功率:在最坏的情况下,简单算法将消耗超过100个CPU周期,因为它将循环20次(64位为41次)。我在这里提出的算法永远不会超过25个周期。

扩展到64位

将上述算法扩展到64位是微不足道的 - 只需再添加一个步骤。以下是上述算法的64位版本,针对没有高效64位除法的处理器进行了优化:

bool IsPowerOfThree(ulong nL)
{
  // General algorithm only
  ulong rL;
  nL = Math.DivRem(nL, 3486784401, out rL); if(nL!=0 && rL!=0) return false;
  nL = Math.DivRem(nL+rL,   59049, out rL); if(nL!=0 && rL!=0) return false;
  uint n = (uint)nL + (uint)rL;
  n = Math.DivRem(n,   243, out r); if(n!=0 && r!=0) return false;
  n = Math.DivRem(n+r,  27, out r); if(n!=0 && r!=0) return false;
  n += r;
  return n==1 || n==3 || n==9;

}

新常数是3 ^ 20。从方法的顶部省略了优化线,因为在我们假设64位除法很慢的情况下,它们实际上会减慢速度。

为何此技术有效

说我想知道“100000000000000000”是10的幂。我可能会按照以下步骤操作:

  1. 我除以10 ^ 10得到10000000的商和余数为0.这些加到10000000。
  2. 我除以10 ^ 5得到100的商和0的余数。这些加到100。
  3. 我除以10 ^ 3得到0和余数为100的商。这些加到100。
  4. 我除以10 ^ 2并得到1的商和0的余数。这些加1。
  5. 因为我以10的幂开始,每次除以10的幂时,我得到零商或零余数。如果我开始使用除10的幂之外的任何东西,我迟早会以非零商或余数结束。

    在这个例子中,我选择了10,5和3的指数来匹配之前提供的代码,并添加了2只是为了它。其他指数也可以工作:有一个简单的算法可以选择理想的指数,给出你的最大输入值和输出中允许的最大功率10,但是这个余量没有足够的空间来容纳它。

    注意:在整个解释过程中,您可能一直在考虑基数十,但是如果你在三垒中考虑,那么上面的整个解释可以被读取和理解相同,除了指数将有表达方式不同(而不是“10”,“5”,“3”和“2”我不得不说“101”,“12”,“10”和“2”)。

答案 4 :(得分:26)

如果(log n)/(log 3)是积分则n是3的幂。

答案 5 :(得分:10)

递归除以3,检查余数为零并重新应用于商。

请注意,1是有效答案,因为零功率为1的3是要注意的边缘情况。

答案 6 :(得分:10)

非常有趣的问题,我喜欢answer from starblue, 这是他的算法的变体,它会更快地收敛到解决方案:

private bool IsPow3(int n)
{
    if (n == 0) return false;
    while (n % 9 == 0)
    {
        n /= 9;
    }
    return (n == 1 || n == 3);
}

答案 7 :(得分:8)

这是对这些问题下所有优秀答案的总结,性能数据可以从LeetCode article找到。

1。循环迭代

时间复杂度O(log(n)),空间复杂度O(1)

public boolean isPowerOfThree(int n) {
    if (n < 1) {
        return false;
    }

    while (n % 3 == 0) {
        n /= 3;
    }

    return n == 1;
}

2。基本转换

将整数转换为基数为3的数字,并检查它是否被写为前导1后跟全部为0.它的灵感来自于通过执行n & (n - 1) == 0 <来检查数字是否为2的幂的解决方案/ p>

时间复杂度:O(log(n))取决于语言和编译器,空间复杂度:O(log(n))

public boolean isPowerOfThree(int n) {
    return Integer.toString(n, 3).matches("^10*$");
}

3数学

如果n = 3^i,则为i = log(n) / log(3),从而进入解决方案

时间复杂度:取决于语言和编译器,空间复杂度:O(1)

public boolean isPowerOfThree(int n) {
    return (Math.log(n) / Math.log(3) + epsilon) % 1 <= 2 * epsilon;
}

4个整数限制

因为3^19 = 1162261467是32位整数中3个数字拟合的最大幂,所以我们可以做到

时间复杂度:O(1),空间复杂度:O(1)

public boolean isPowerOfThree(int n) {
    return n > 0 && 1162261467 % n == 0;
}

使用Set

的5个整数限制

这个想法类似于#4,但使用一个集来存储3个数字的所有可能功率(从3 ^ 0到3 ^ 19)。它使代码更具可读性。

6 Recursive(C ++ 11)

此解决方案特定于C ++ 11,使用模板元编程,因此编译器将使用计算结果替换调用isPowerOf3<Your Input>::cValue

时间复杂度:O(1),空间复杂度:O(1)

template<int N>
struct isPowerOf3 {
    static const bool cValue = (N % 3 == 0) && isPowerOf3<N / 3>::cValue;
};

template<>
struct isPowerOf3<0> {
    static const bool cValue = false;
};

template<>
struct isPowerOf3<1> {
    static const bool cValue = true;
};

int main() {
    cout<<isPowerOf3<1162261467>::cValue;
    return 0;
}

答案 8 :(得分:7)

在2的幂之间最多有三个幂。 所以以下是一个快速测试:

  1. 通过查找数字中前导n位的位置来查找1的二进制对数。这是非常快的,因为现代处理器有一个特殊的指令。 (否则你可以通过一点点思考来做,请参阅Bit Twiddling Hacks)。

  2. 在此位置索引的表中查找3的潜在幂并与n进行比较(如果没有3的幂,则可以存储具有不同二进制对数的任何数字)。

  3. 如果等于,则返回yes,否则为no。

  4. 运行时主要取决于访问表条目所需的时间。如果我们使用机器整数,表很小,可能在缓存中(我们使用它数百万次,否则这种优化级别没有意义)。

答案 9 :(得分:5)

简单而恒定的解决方案:

return n == power(3, round(log(n) / log(3)))

答案 10 :(得分:4)

您的输入有多大?使用O(log(N))内存,你可以做得更快,O(log(log(N))。预先计算3的幂,然后对预先计算的值进行二进制搜索。

答案 11 :(得分:4)

对于非常大的数字n,您可以使用以下数学技巧来加速

的操作
  n % 3 == 0

这是非常慢的,很可能是依赖于重复检查余数的任何算法的阻塞点。你必须理解模运算来跟踪我正在做的事情,这是基本数论的一部分。

令x =Σ k a k 2 k 为感兴趣的数量。我们可以将和的上限设为∞,理解为对于某些k> k = 0。 M.然后

0≡x≡Σ k a k 2 k ≡Σ k a 2k < / sub> 2 2k + a 2k + 1 2 2k + 1 ≡Σ k 2 2k (a 2k + a 2k + 1 2)≡Σ k a 2k + a < sub> 2k + 1 2(mod 3)

因为2 2k ≡4 k ≡1 k ≡1(mod 3)。

给出数字x的二进制表示,其中2n + 1位为

x 0 x 1 x 2 ... x 2n + 1

其中x k ∈{0,1}你可以将奇数偶数组分组

(x 0 x 1 )(x 2 x 3 )...(x 2n x 2n + 1 )。

令q表示形式(10)的配对数,并且令r表示形式(0 1)的配对数。然后从上面的等式得到3 | x当且仅当3 | (q + 2r)。此外,当且仅当q和r在除以3时具有相同的余数时,才能显示3 |(q + 2r)。

因此,确定数字是否可被3整除的算法可以如下进行

 q = 0, r = 0
 for i in {0,1, .., n}
     pair <- (x_{2i} x_{2i+1})
     if pair == (1 0)
         switch(q)
             case 0:
                 q = 1;
                 break;
             case 1:
                 q = 2;
                 break;
             case 2:
                 q = 0;
                 break;
     else if pair == (0 1)
         switch(r)
             case 0:
                 r = 1;
                 break;
             case 1:
                 r = 2;
                 break;
             case 2:
                 r = 0;
 return q == r

此算法比使用%。

更有效

---多年后编辑----

我花了几分钟时间在python中实现了这个基本版本,它检查了所有数字的真实性,最高可达10 ^ 4。我在下面提供它以供参考。显然,使用这个可以实现尽可能接近硬件。通过改变推导,可以将该扫描技术扩展到任何想要的数字。我还猜想算法的“扫描”部分可以用类似于FFT的递归O(log n)类型公式重新制定,但我必须考虑它。

#!/usr/bin/python

def bits2num(bits):
    num = 0
    for i,b in enumerate(bits):
        num += int(b) << i
    return num

def num2bits(num):
    base = 0
    bits = list()
    while True:
        op = 1 << base
        if op > num:
            break
        bits.append(op&num !=0)
        base += 1
    return "".join(map(str,map(int,bits)))[::-1]

def div3(bits):

    n = len(bits)

    if n % 2 != 0:
        bits = bits + '0'

    n = len(bits)

    assert n % 2 == 0

    q = 0
    r = 0
    for i in range(n/2):
        pair = bits[2*i:2*i+2]
        if pair == '10':
            if q == 0:
                q = 1
            elif q == 1:
                q = 2
            elif q == 2:
                q = 0
        elif pair == '01':
            if r == 0:
                r = 1
            elif r == 1:
                r = 2
            elif r == 2:
                r = 0
        else:
            pass

    return q == r

for i in range(10000):
    truth = (i % 3)  == 0
    bits = num2bits(i)
    check  = div3(bits)
    assert truth == check

答案 12 :(得分:4)

这是C:{/ p>中Ray Burns' method的一个很好的快速实现

bool is_power_of_3(unsigned x) {
    if (x > 0x0000ffff)
        x *= 0xb0cd1d99;    // multiplicative inverse of 59049
    if (x > 0x000000ff)
        x *= 0xd2b3183b;    // multiplicative inverse of 243
    return x <= 243 && ((x * 0x71c5) & 0x5145) == 0x5145;
}

它使用multiplicative inverse技巧首先除以3 ^ 10然后除以3 ^ 5。最后,需要检查结果是1,3,9,27,81还是243,这是通过试错法找到的一些简单散列来完成的。

在我的CPU(Intel Sandy Bridge)上,速度非常快,但速度不如method of starblue that uses the binary logarithm(在该CPU上的硬件中实现)。但是在没有这样的指令的CPU上,或者当不希望查找表时,它可能是另一种选择。

答案 13 :(得分:3)

你可以比重复分割做得更好,这需要O(lg(X)* |分割|)时间。基本上你是对3的幂进行二元搜索。实际上我们将在N上进行二进制搜索,其中3 ^ N =输入值)。设置N的Pth二进制数对应于乘以3 ^(2 ^ P),并且可以通过重复平方来计算形式3 ^(2 ^ P)的值。

<强>算法

  • 让输入值为X。
  • 生成重复平方值的列表L,一旦传递X即结束。
  • 让您的候选人值为T,初始化为1。
  • 对于反向L中的每个E,如果T * E <= X则让T * = E.
  • 返回T == X。

<强>复杂度:

O(lg(lg(X))* |乘法|) - 生成和迭代L需要lg(lg(X))迭代,乘法是迭代中最昂贵的操作。

答案 14 :(得分:3)

最快的解决方案是测试another answer中给出的n > 0 && 3**19 % n == 0还是完美哈希(下方)。首先,我给出了两个基于乘法的解决方案。

乘法

我想知道为什么每个人都错过了乘法比分裂快得多:

for (int i=0, pow=1; i<=19, pow*=3; ++i) {
    if (pow >= n) {
        return pow == n;
    }
}
return false;

尝试所有的力量,当它变得太大时停止。避免溢出,因为3**19 = 0x4546B3DB是签名32位int中的最大功率拟合。

使用二进制搜索进行乘法

二进制搜索可能看起来像

int pow = 1;
int next = pow * 6561; // 3**8
if (n >= next) pow = next;
next = pow * 81; // 3**4
if (n >= next) pow = next;
next = pow * 81; // 3**4; REPEATED
if (n >= next) pow = next;
next = pow * 9; // 3**2
if (n >= next) pow = next;
next = pow * 3; // 3**1
if (n >= next) pow = next;
return pow == next;

重复一步,以便可以准确地达到最大指数19 = 8+4+4+2+1

完美哈希

有20个幂的三个适合签名的32位int,所以我们采用32个元素的表。通过一些实验,我发现了完美的哈希函数

def hash(x):
    return (x ^ (x>>1) ^ (x>>2)) & 31;

将每个权力映射到0到31之间的不同索引。其余的东西是微不足道的:

// Create a table and fill it with some power of three.
table = [1 for i in range(32)]
// Fill the buckets.
for n in range(20): table[hash(3**n)] = 3**n;

现在我们有了

table = [
     1162261467, 1, 3, 729, 14348907, 1, 1, 1,
     1, 1, 19683, 1, 2187, 81, 1594323, 9,
     27, 43046721, 129140163, 1, 1, 531441, 243, 59049,
     177147, 6561, 1, 4782969, 1, 1, 1, 387420489]

可以通过

快速测试
def isPowerOfThree(x):
    return table[hash(x)] == x

答案 15 :(得分:1)

通过定义一个简单的函数来为您运行检查,您的问题很容易回答。下面显示的示例实现是用Python编写的,但如果需要,应该很难用其他语言重写。与此答案的最后一个版本不同,下面显示的代码更可靠。

Python 3.6.0 (v3.6.0:41df79263a11, Dec 23 2016, 08:06:12) [MSC v.1900 64 bit (AMD64)] on win32
Type "copyright", "credits" or "license()" for more information.
>>> import math
>>> def power_of(number, base):
    return number == base ** round(math.log(number, base))

>>> base = 3
>>> for power in range(21):
    number = base ** power
    print(f'{number} is '
          f'{"" if power_of(number, base) else "not "}'
          f'a power of {base}.')
    number += 1
    print(f'{number} is '
          f'{"" if power_of(number, base) else "not "}'
          f'a power of {base}.')
    print()


1 is a power of 3.
2 is not a power of 3.

3 is a power of 3.
4 is not a power of 3.

9 is a power of 3.
10 is not a power of 3.

27 is a power of 3.
28 is not a power of 3.

81 is a power of 3.
82 is not a power of 3.

243 is a power of 3.
244 is not a power of 3.

729 is a power of 3.
730 is not a power of 3.

2187 is a power of 3.
2188 is not a power of 3.

6561 is a power of 3.
6562 is not a power of 3.

19683 is a power of 3.
19684 is not a power of 3.

59049 is a power of 3.
59050 is not a power of 3.

177147 is a power of 3.
177148 is not a power of 3.

531441 is a power of 3.
531442 is not a power of 3.

1594323 is a power of 3.
1594324 is not a power of 3.

4782969 is a power of 3.
4782970 is not a power of 3.

14348907 is a power of 3.
14348908 is not a power of 3.

43046721 is a power of 3.
43046722 is not a power of 3.

129140163 is a power of 3.
129140164 is not a power of 3.

387420489 is a power of 3.
387420490 is not a power of 3.

1162261467 is a power of 3.
1162261468 is not a power of 3.

3486784401 is a power of 3.
3486784402 is not a power of 3.

>>> 

注意:最后一次修订导致此答案与TMS' answer几乎相同。

答案 16 :(得分:0)

另一种方法是在编译时生成一个表。好的是,你可以将它扩展到4,5,6,7的幂,无论

template<std::size_t... Is>
struct seq
{  };

template<std::size_t N, std::size_t... Is>
struct gen_seq : gen_seq<N-1, N-1, Is...>
{  };

template<std::size_t... Is>
struct gen_seq<0, Is...> : seq<Is...>
{  };

template<std::size_t N>
struct PowersOfThreeTable
{
    std::size_t indexes[N];
    std::size_t values[N];

    static constexpr std::size_t size = N;
};

template<typename LambdaType, std::size_t... Is>
constexpr PowersOfThreeTable<sizeof...(Is)>
    generatePowersOfThreeTable(seq<Is...>, LambdaType evalFunc)
{
    return { {Is...}, {evalFunc(Is)...} };
}

template<std::size_t N, typename LambdaType>
constexpr PowersOfThreeTable<N> generatePowersOfThreeTable(LambdaType evalFunc)
{
    return generatePowersOfThreeTable(gen_seq<N>(), evalFunc);
}

template<std::size_t Base, std::size_t Exp>
struct Pow
{
    static constexpr std::size_t val = Base * Pow<Base, Exp-1ULL>::val;
};

template<std::size_t Base>
struct Pow<Base, 0ULL>
{
    static constexpr std::size_t val = 1ULL;
};

template<std::size_t Base>
struct Pow<Base, 1ULL>
{
    static constexpr std::size_t val = Base;
};

constexpr std::size_t tableFiller(std::size_t val)
{ 
    return Pow<3ULL, val>::val;
}

bool isPowerOfThree(std::size_t N)
{
    static constexpr unsigned tableSize = 41; //choosen by fair dice roll

    static constexpr PowersOfThreeTable<tableSize> table = 
            generatePowersOfThreeTable<tableSize>(tableFiller);

    for(auto a : table.values)
        if(a == N)
            return true;
    return false;
}

答案 17 :(得分:0)

设置基于解决方案......

DECLARE @LastExponent smallint, @SearchCase decimal(38,0)

SELECT
    @LastExponent = 79, -- 38 for bigint
    @SearchCase = 729

;WITH CTE AS
(
    SELECT
        POWER(CAST(3 AS decimal(38,0)), ROW_NUMBER() OVER (ORDER BY c1.object_id)) AS Result,
        ROW_NUMBER() OVER (ORDER BY c1.object_id) AS Exponent
    FROM
        sys.columns c1, sys.columns c2
)
SELECT
    Result, Exponent
FROM
    CTE
WHERE
    Exponent <= @LastExponent
    AND
    Result = @SearchCase

使用SET STATISTICS TIME ON,它记录最低可能的1毫秒。

答案 18 :(得分:0)

我测量了某些解决方案的时间(C#,平台目标x64)。

using System;
class Program
{
    static void Main()
    {
        var sw = System.Diagnostics.Stopwatch.StartNew();
        for (uint n = ~0u; n > 0; n--) ;
        Console.WriteLine(sw.Elapsed);              // nada   1.1 s
        sw.Restart();
        for (uint n = ~0u; n > 0; n--) isPow3a(n);
        Console.WriteLine(sw.Elapsed);              // 3^20  17.3 s
        sw.Restart();
        for (uint n = ~0u; n > 0; n--) isPow3b(n);
        Console.WriteLine(sw.Elapsed);              // % /   10.6 s
        Console.Read();
    }

    static bool isPow3a(uint n)  // Elric
    {
        return n > 0 && 3486784401 % n == 0;
    }

    static bool isPow3b(uint n)  // starblue
    {
        if (n > 0) while (n % 3 == 0) n /= 3;
        return n == 1;
    }
}

另一种方式(分裂头发)。

using System;
class Program
{
    static void Main()
    {
        Random rand = new Random(0); uint[] r = new uint[512];
        for (int i = 0; i < 512; i++)
            r[i] = (uint)(rand.Next(1 << 30)) << 2 | (uint)(rand.Next(4));
        var sw = System.Diagnostics.Stopwatch.StartNew();
        for (int i = 1 << 23; i > 0; i--)
            for (int j = 0; j < 512; j++) ;
        Console.WriteLine(sw.Elapsed);                    //   0.3 s
        sw.Restart();
        for (int i = 1 << 23; i > 0; i--)
            for (int j = 0; j < 512; j++) isPow3c(r[j]);
        Console.WriteLine(sw.Elapsed);                    //  10.6 s
        sw.Restart();
        for (int i = 1 << 23; i > 0; i--)
            for (int j = 0; j < 512; j++) isPow3b(r[j]);
        Console.WriteLine(sw.Elapsed);                    //   9.0 s
        Console.Read();
    }

    static bool isPow3c(uint n)
    { return (n & 1) > 0 && 3486784401 % n == 0; }

    static bool isPow3b(uint n)
    { if (n > 0) while (n % 3 == 0) n /= 3; return n == 1; }
}

答案 19 :(得分:0)

用于检查数字是否为 3 的幂的 Python 程序。

    def power(Num1):
        while Num1 % 3 == 0:
            Num1 /= 3
        return Num1 == 1


    Num1 = int(input("Enter a Number: "))
    print(power(Num1))

答案 20 :(得分:-1)

这是一个通用算法,用于查明数字是否是另一个数字的幂:

bool IsPowerOf(int n,int b)
{
    if (n > 1)
    {
        while (n % b == 0)
        {
            n /= b;
        }
    }
    return n == 1;
}

答案 21 :(得分:-1)

#include<iostream>
#include<string>
#include<cmath>
using namespace std;
int main()
{
     int n, power=0;
      cout<<"enter a number"<<endl;
      cin>>n;
  if (n>0){

     for(int i=0; i<=n; i++)
     {

         int r=n%3;

            n=n/3;
         if (r==0){
            power++;
         }

         else{
               cout<<"not exactly power of 3";
                return 0;

             }
     }

   }

         cout<<"the power is "<<power<<endl;
  }

答案 22 :(得分:-1)

这是一个恒定的时间方法!是。 O(1)。 对于固定长度的数字,比如32位。

鉴于我们需要检查整数n是否为3的幂,让我们从已经掌握的信息开始考虑这个问题。

1162261467是3中最大的幂,可以放入Java int。
1162261467 = 3^19 + 0

给定的n可以表示为[(3的幂)+(某些x)]。我认为能够证明如果x为0(发生 iff n是3的幂)是相当基础的,1162261467%n = 0。

一般的想法是,如果X是3的幂,X可以表示为Y/3a,其中a是某个整数,X&lt; Y.它遵循Y&lt;完全相同的原理。 X. Y = X的情况是基本的。

因此,要检查给定的整数n是否为3的幂,请检查n > 0 && 1162261467 % n == 0是否。

答案 23 :(得分:-1)

Python解决方案

from math import floor
from math import log

def IsPowerOf3(number):
  p = int(floor(log(number) / log(3)))
  power_floor = pow(3, p)
  power_ceil = power_floor * 3
  if power_floor == number or power_ceil == number:
    return True
  return False

这比简单的3分解更快。

证明:3 ^ p =数字

p log(3)= log(number)(记录两面)

p = log(number)/ log(3)

答案 24 :(得分:-1)

Python:

return n > 0 and 1162261467 % n == 0

OR 计算日志:

lg = round(log(n,3))
return 3**lg == n

第一种方法比第二种方法快。

相关问题