leetcode 326. Power of Three

257 篇文章 17 订阅

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?

这道题要求很简单,就是判断n是否是3的乘方。难点在于不能用循环和递归。(注意:1是3的乘方,因为1是3的0次方。)

循环和递归的解法就不提了。这道题有这几种解法:

Method 1

算出Int最大值范围内的3的最大乘方数是:1162261467,判断n能不能整除它。

public boolean isPowerOfThree(int n) {
    // 1162261467 is 3^19,  3^20 is bigger than int  
    return ( n>0 &&  1162261467%n==0);
}

Method 2

如果 log10(n) / log10(3) 得到的是整数,那么n就是3的成分。 但是这里  需要注意的是, java的Math.log(x)方法默认的是自然数底数,即以e作为底数。但是这里不能够使用自然数底数,因为java在这里会有 round off error for n=243 ,更像是一个巧合。当 n=243, 我们得到的是下面的结果。

log(243) = 5.493061443340548    log(3) = 1.0986122886681098
   ==> log(243)/log(3) = 4.999999999999999

log10(243) = 2.385606273598312    log10(3) = 0.47712125471966244
   ==> log10(243)/log10(3) = 5.0

这是因为 log(3) 实际上轻微地比它真正的值要大,导致了 求比结果 比 真正的值更小。

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

如果害怕出现这种round off error的巧合出错,可以用下面两种方案来弥补:

public boolean isPowerOfThree(int n) {
    return n==0 ? false : n==Math.pow(3, Math.round(Math.log(n) / Math.log(3)));
}

或者

public boolean isPowerOfThree(int n) {
    return n>0 && Math.abs(Math.log10(n)/Math.log10(3)-Math.ceil(Math.log10(n)/Math.log10(3))) < Double.MIN_VALUE;
}

 
 
Method 3 Cheating Method

cheating method其实并不是一个好方法,但是对于这样的 乘方 问题,如果我们需要检查很多次,那么先把所有可能值存到hashset中也不失为一种好办法。 

public boolean isPowerOfThree(int n) {
    HashSet<Integer> set = new HashSet<>(Arrays.asList(1, 3, 9, 27, 81, 243, 729, 2187, 6561, 19683, 59049, 177147, 531441, 1594323, 4782969, 14348907, 43046721, 129140163, 387420489, 1162261467));
    return set.contains(n);
}

Method 4

思路是把 n 转化为三进制的表示,然后检查 该三进制字符串 是否呈现 100.....的格式(其中0的个数>=0)。format 10* where 0* means k zeros with k>=0.

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

这道题有solutions:https://leetcode.com/problems/power-of-three/solution/

Solution


Approach #1 Loop Iteration [Accepted]

Java

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

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

        return n == 1;
    }
}

Complexity Analysis

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

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


Approach #2 Base Conversion 进制转换 [Accepted]

在十进制中,所有10的乘方的数字 都以 1 开头,之后跟着 (比如 10, 100, 1000)。 这对于其他进制和对应的乘方也适用。所以我们可以把 n 转化为三进制的表达形式,如果它的格式是100...0, 那么它就是3的乘方。

使用以下的正则表达式来判断:字符串是否以 1 开头 ^1, 后面跟着 0个或者更多个数字 0 0* ,并且字符串中不包含其他的东西 $.

Java

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

Complexity Analysis

  • Time complexity : 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(log_3n)O(log3n).
    • String.matches() - Method iterates over the entire string. The number of digits in the base 3 representation of n is O(log_3n)O(log3n).
  • Space complexity : O(log_3n)O(log3n).

    We are using two additional variables,

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

Approach #3 Mathematics [Accepted]

log方法:

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

只有当 i 是整数时,n 才是3的乘方。判断一个数是不是整数,我们可以用 % 1 来取出小数部分,检查小数部分是否是0。

Java

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

Attention

当我们开始使用 double时,就有可能产生精度错误,这种解法就有问题。这意味着当比较 double数字时,我们不能使用 == 。因为 Math.log10(n) / Math.log10(3) 的结果可能是 5.0000001 或者4.9999999。为了解决这个问题,我们可以使用 epsilon来避免这个问题。令final double epsilon=0.00000001;(epsilon通常表示表示大于零的最小正Double值。这里可以自己定义,或者直接令epsilon=Double.MIN_VALUE。)

需要注意的是,Integer.MIN_VALUE自不必说,就是32位整型能存储的最小数字:0x80000000,是一个负数。但是Double.MIN_VALUE却是一个正数,Double.MIN_VALUE表示的是64位双精度值能表示的最小正数。如果需要用到Double的负无穷,可以用Double.NEGATIVE_INFINITY。

Java

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

Complexity Analysis

  • Time complexity : UnknownUnknown 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). We are not using any additional memory. The epsilon variable can be inlined.


Approach #4 Integer Limitations [Accepted]

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


Java

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

Complexity Analysis

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

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

Performance Measurements

Iterations 10^6106 10^7107 10^8108 10^9109 MaxintMaxint
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

References


Python网络爬虫与推荐算法新闻推荐平台:网络爬虫:通过Python实现新浪新闻的爬取,可爬取新闻页面上的标题、文本、图片、视频链接(保留排版) 推荐算法:权重衰减+标签推荐+区域推荐+热点推荐.zip项目工程资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松复刻,拿到资料包后可轻松复现出一样的项目,本人系统开发经验充足(全领域),有任何使用问题欢迎随时与我联系,我会及时为您解惑,提供帮助。 【资源内容】:包含完整源码+工程文件+说明(如有)等。答辩评审平均分达到96分,放心下载使用!可轻松复现,设计报告也可借鉴此项目,该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的。 【提供帮助】:有任何使用问题欢迎随时与我联系,我会及时解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 下载后请首先打开README文件(如有),项目工程可直接复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值