231. Power of Two

Given an integer, write a function to determine if it is a power of two.

较好的思路:

讲这个数与其前一个数作与运算,一旦为0满足要求,否则不满足要求

官方解答:

Power of 2 means only one bit of n is '1', so use the trick n&(n-1)==0 to judge whether that is the case

class Solution {
public:
    bool isPowerOfTwo(int n) {
        if(n<=0) return false;
        return !(n&(n-1));
    }
};

类似的题目有

326. Power of Three

Given an integer, write a function to determine if it is a power of three.

Follow up:
Could you do it without using any loop / recursion?

官方解答:

Solution

In this article we will look into ways of speeding up simple computations and why that is useful in practice.


Approach #1 Loop Iteration [Accepted]

One simple way of finding out if a number n is a power of a numberb is to keep dividing n by b as long as the remainder is0. This is because we can write

nn=bx=b×b××b

Hence it should be possible to divide n by b x times, every time with a remainder of0 and the end result to be 1.

Java

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

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

        return n == 1;
    }
}

Notice that we need a guard to check that n != 0, otherwise the while loop will never finish. For negative numbers, the algorithm does not make sense, so we will include this guard as well.

Complexity Analysis

  • Time complexity : O(logb(n))O(log_b(n))O(logb(n)). In our case that is O(log3n)O(log_3n)O(log3n). The number of divisions is given by that logarithm.

  • Space complexity : O(1)O(1)O(1). We are not using any additional memory.


Approach #2 Base Conversion [Accepted]

In Base 10, all powers of 10 start with the digit 1 and then are followed only by0 (e.g. 10, 100, 1000). This is true for other bases and their respective powers. For instance inbase 2, the representations of 10210_2102,1002100_21002 and 100021000_210002 are 2102_{10}210,4104_{10}410 and 8108_{10}810 respectively. Therefore if we convert our number to base 3 and the representation is of the form 100...0, then the number is a power of 3.

Proof

Given the base 3 representation of a number as the array s, with the least significant digit on index 0, the formula for converting from base3 to base 10 is:

∑i=0len(s)−1s[i]∗3i\sum_{i=0}^{len(s) - 1} s[i] * 3^{i}i=0len(s)1s[i]3i

Therefore, having just one digit of 1 and everything else 0 means the number is a power of 3.

Implementation

All we need to do is convert [4] the number to base 3 and check if it is written as a leading1 followed by all 0.

A couple of built-in Java functions will help us along the way.

String baseChange = Integer.toString(number, base);

The code above converts number into base base and returns the result as aString. For example, Integer.toString(5, 2) == "101" andInteger.toString(5, 3) == "12".

boolean matches = myString.matches("123");

The code above checks if a certain Regular Expression[2] pattern exists inside a string. For instance the above will return true if the substring "123" exists inside the stringmyString.

boolean powerOfThree = baseChange.matches("^10*$")

We will use the regular expression above for checking if the string starts with1 ^1, is followed by zero or more 0s0* and contains nothing else $.

Java

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

Complexity Analysis

  • Time complexity : O(log3n)O(log_3n)O(log3n).

    Assumptions:

    • Integer.toString() - Base conversion is generally implemented as a repeated division. The complexity of should be similar to our approach #1:O(log3n)O(log_3n)O(log3n).
    • String.matches() - Method iterates over the entire string. The number of digits in the base 3 representation ofn is O(log3n)O(log_3n)O(log3n).
  • Space complexity : O(log3n)O(log_3n)O(log3n).

    We are using two additional variables,

    • The string of the base 3 representation of the number (size log3nlog_3nlog3n)
    • The string of the regular expression (constant size)

Approach #3 Mathematics [Accepted]

We can use mathematics as follows

n=3ii=log3(n)i=logb(n)logb(3)

n is a power of three if and only if i is an integer. In Java, we check if a number is an integer by taking the decimal part (using% 1) and checking if it is 0.

Java

public class Solution {
    public boolean isPowerOfThree(int n) {
        return (Math.log10(n) / Math.log10(3)) % 1 == 0;
    }
}

Common pitfalls

This solution is problematic because we start using doubles, which means we are subject to precision errors. This means, we should never use== when comparing doubles. That is because the result ofMath.log10(n) / Math.log10(3) could be 5.0000001 or 4.9999999. This effect can be observed by using the function Math.log() instead ofMath.log10().

In order to fix that, we need to compare the result against an epsilon.

Java

return (Math.log(n) / Math.log(3) + epsilon) % 1 <= 2 * epsilon;

Complexity Analysis

  • Time complexity : UnknownUnknownUnknown The expensive operation here is Math.log, which upper bounds the time complexity of our algorithm. The implementation is dependent on the language we are using and the compiler[3]

  • Space complexity : O(1)O(1)O(1). We are not using any additional memory. The epsilon variable can be inlined.


Approach #4 Integer Limitations [Accepted]

An important piece of information can be deduced from the function signature

public boolean isPowerOfThree(int n)

In particular, n is of type int. In Java, this means it is a 4 byte, signed integer [ref]. The maximum value of this data type is2147483647. Three ways of calculating this value are

  • Google
  • System.out.println(Integer.MAX_VALUE);
  • MaxInt = 2322−1\frac{ 2^{32} }{2} - 122321 since we use 32 bits to represent the number, half of the range is used for negative numbers and 0 is part of the positive numbers

Knowing the limitation of n, we can now deduce that the maximum value ofn that is also a power of three is 1162261467. We calculate this as:

3⌊log3MaxInt⌋=3⌊19.56⌋=319=11622614673^{\lfloor{}log_3{MaxInt}\rfloor{}} = 3^{\lfloor{}19.56\rfloor{}} = 3^{19} = 11622614673log3MaxInt=319.56=319=1162261467

Therefore, the possible values of n where we should return true are 303^030,313^131 ... 3193^{19}319. Since 3 is a prime number, the only divisors of 3193^{19}319 are 303^030,313^131 ... 3193^{19}319, therefore all we need to do is divide 3193^{19}319 by n. A remainder of 0 means n is a divisor of3193^{19}319 and therefore a power of three.

Java

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

Complexity Analysis

  • Time complexity : O(1)O(1)O(1). We are only doing one operation.

  • Space complexity : O(1)O(1)O(1). We are not using any additional memory.

Performance Measurements

Single runs of the function make it is hard to accurately measure the difference of the two solutions. On LeetCode, on theAccepted Solutions Runtime Distribution page, all solutions being between15 ms and 20 ms. For completeness, we have proposed the following benchmark to see how the two solutions differ.

Java Benchmark Code

public static void main(String[] args) {
    Solution sol = new Solution();
    int iterations = 1; // See table header for this value
    for (int i = 0; i < iterations; i++) {
        sol.isPowerOfThree(i);
    }
}

In the table below, the values are in seconds.

Iterations10610^610610710^710710810^810810910^9109MaxintMaxintMaxint
Java Approach #1 (Naive)0.040.070.302.475.26
Java Approach #2 (Strings)0.684.0238.90409.16893.89
Java Approach #3 (Logarithms)0.090.504.5945.5397.50
Java Approach #4 (Fast)0.040.060.080.410.78

As we can see, for small values of N, the difference is not noticeable, but as we do more iterations and the values ofn passed to isPowerOfThree() grow, we see significant boosts in performance for Approach #4.

Conclusion

Simple optimizations like this might seem negligible, but historically, when computation power was an issue, it allowed certain computer programs (such as Quake 3[1]) possible.


类似的题目还有:

342. Power of Four

Given an integer (signed 32 bits), write a function to check whether it is a power of 4.

Example:
Given num = 16, return true.Given num = 5, return false.

Follow up: Could you solve it without loops/recursion?

官方解答:

 public boolean isPowerOfFour(int num) {
        return num > 0 && (num&(num-1)) == 0 && (num & 0x55555555) != 0;
        //0x55555555 is to get rid of those power of 2 but not power of 4
        //so that the single 1 bit always appears at the odd position 
    }



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值