题目
给定一个整数,编写一个函数,判断该整数是否 3 的幂。
后续:
你的函数能够不使用任何循环/递归吗?
难度:容易
编程语言:C++
分析
程序框架为:
1 2 3 4 5 6
| class Solution { public: bool isPowerOfThree(int n) { } };
|
我们先列举一些 3 的幂:
- 30 = 1
- 31 = 3
- 32 = 9
- 33 = 27
- 34 = 81
- 35 = 243
- 36 = 729
- 37 = 2187
- 38 = 6561
- 39 = 19683
- 310 = 59049
思路如下:
- 如果 n == 1,那么 return true
- 如果 n > 1,不断除以 3,如果出现余数,则 return false
如果一直不出现余数,直到商为 1,则 return true
伪代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| bool isPowerOfThree(int n) { if (n < 1) { return false; } if (n == 1) { return true; } while (n > 1) { int remainder = n % 3; if (remainder == 0) { n = n / 3; } else { return false; } } return true; }
|
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| #include <iostream> using namespace std; class Solution { public: bool isPowerOfThree(int n) { if (n < 1) { return false; } if (n == 1) { return true; } while (n > 1) { int remainder = n % 3; if (remainder == 0) { n = n / 3; } else { return false; } } return true; } }; int main() { Solution sol; cout << sol.isPowerOfThree(0) << endl; cout << sol.isPowerOfThree(1) << endl; cout << sol.isPowerOfThree(3) << endl; cout << sol.isPowerOfThree(9) << endl; cout << sol.isPowerOfThree(27) << endl; cout << sol.isPowerOfThree(28) << endl; }
|
提交到 Leetcode,Accepted! :) 运行时间为 136ms。
后续
你的函数能够不使用任何循环/递归吗?
我们回看一些 3 的幂,看看能不能找出一些规律:
- 30 = 1
- 31 = 3
- 32 = 9
- 33 = 27 // 2 + 7 = 9
- 34 = 81 // 8 + 1 = 9
- 35 = 243 // 2 + 4 + 3 = 9
- 36 = 729 // 7 + 2 + 9 = 18
- 37 = 2187 // 2 + 1 + 8 + 7 = 18
- 38 = 6561 // 6 + 5 + 6 + 1 = 18
- 39 = 19683 // 1 + 9 + 6 + 8 + 3 = 27
- 310 = 59049 // 5 + 9 + 0 + 4 + 9 = 27
可以看到,每个幂的各位相加之和也是 3 的幂。但不是各位相加之和是 3 的幂的数就一定是 3 的幂,如 45。
想起了一个很简单的数学办法:求 log 值。
- log31 = 0
- log33 = 1
- log39 = 2
- log327 = 3
- log381 = 4
- log3243 = 5
- log3729 = 6
我们调用 double m = log3n,但是 m 是非常接近实际整数值结果的 double 值,这时候我们认为,只要 |m - 整数值| 少于某个误差范围(如 10-5),两者相等。
伪代码如下:
1 2 3 4 5 6
| bool isPowerOfThree(int n) { double m = Math.log(n, 3); double roundM = Math.round(m); // roundM 是最接近 m 的整数值 double absoluteDiff = abs(m - roundM); // 取两者之差的绝对值 return (absoluteDiff < 10^-5); }
|
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| #include <iostream> #include <math.h> using namespace std; class Solution { public: double EPSILON = 10e-5; bool isPowerOfThree2(int n) { double m = logbase(n, 3); double roundM = round(m); double absoluteDiff = abs(m - roundM); return (absoluteDiff < EPSILON); } double logbase(double a, double base) { return log(a) / log(base); } }; int main() { Solution sol; cout << sol.isPowerOfThree2(0) << endl; cout << sol.isPowerOfThree2(1) << endl; cout << sol.isPowerOfThree2(3) << endl; cout << sol.isPowerOfThree2(9) << endl; cout << sol.isPowerOfThree2(27) << endl; cout << sol.isPowerOfThree2(28) << endl; }
|
提交到 Leetcode,Wrong Answer,在测试用例 19682,我的函数返回 true,但正确的应该返回 false。
在单步调试后,得出的结果如下:
m = 8.9999537538815275
roundM = 9.0000000000000000
absoluteDiff = 0.000046246118472481612
EPSILON = 0.0001
那么只要把 EPSILON 设为更小的 10-15 即可。
提交到 Leetcode,Accepted! :) 运行时间为 168ms。