LeetCode刷题-2的幂

前言说明

算法学习,日常刷题记录。

题目连接

2的幂

题目内容

给你一个整数n,请你判断该整数是否是2的幂次方。如果是,返回true;否则,返回false。

如果存在一个整数x使得n == 2x ,则认为n是2的幂次方。

示例1:

输入:n = 1

输出:true

解释:20 = 1

示例2:

输入:n = 16

输出:true

解释:24 = 16

示例3:

输入:n = 3

输出:false

示例4:

输入:n = 4

输出:true

示例5:

输入:n = 5

输出:false

提示:

-2^31 <= n <= 2^31 - 1

进阶:

你能够不使用循环/递归解决此问题吗?

分析过程

方法1

首先我们想到最直观的方法,用循环来解决,若一个数是2的幂,必定是2的倍数,而且除以2后还是2的倍数,再除以2循环下去,最后会变成1。但是如果这个数不是2的幂,即使这个数是2的倍数,也不是所有的因子都会是2,所以除以2到最后不会变成1。

class Solution {
    public boolean isPowerOfTwo(int n) {
        if (n < 1) {
            // 2的幂必定大于等于1,若小于1,直接判定为不是
            return false;
        }

        // 若一个数是2的幂,必定是2的倍数,而且除以2后还是2的倍数,再除以2,直到最后为1,如果最后不是1,那么证明这个数虽然是2的倍数,但是不是所有因子都是2,所以不是2的幂
        while (n % 2 == 0) {
            n /= 2;
        }

        // 最后一步判断是否为1,若是1,则证明n是2的幂,若不是1,则证明n不是2的幂
        return n == 1;
    }
}

提交代码后,执行用时1ms,时间击败100.00%的用户,内存消耗35.4MB,空间击败74.67%的用户。

运行结果
方法2

俗话说,学好数理化,走遍天下都不怕。对于算法,俗话也说,学好位运算,刷遍题目都不怕!

看到有点feel的算法题,要先想想能不能用位运算解决。

先来枚举几个2的幂,看看他们的二进制位长什么样。

我们可以发现二进制的幂首先大于等于1,然后除了2的0次幂是1外,其他的2的n次幂,都是只有一个1的位。那么问题就转化成了,如何判断这个数的二进制位只有一个1。

我们拍脑袋就能想到肯定是通过位运算来实现的,那么我们先来找一个例子,例如2的2次幂等于4,二进制表示就是"0100",我们再看4-1=3,3的二进制表示就是"0011",如果两者进行并运算&,那么就会得到二进制"0000",也就是0;如果是5,二进制表示"0101",那么5-1=4,4的二进制表示"0100",如果两者进行并运算&,那么就会得到二进制"0100",所以说一个数和这个数减1进行并运算,即n&(n-1),结果是这个数被去掉最右边的1。

我们上面知道在大于1的整数中,2的幂的二进制位只有一个1,所以我们只需要判断n&(n-1)是否等于0即可,因为2的幂只有一个1,通过&并运算后,会去掉最右边的1,那么二进制位就全部都是0,如果二进制位不全部是0,那么这个数就不是2的幂。

所以这样一来,是不是变得很简单了?一行代码即可解决。

class Solution {
    public boolean isPowerOfTwo(int n) {
        // 2的幂肯定大于等于1,然后通过类似计算汉明距离的方法用&运算把n的最右边的1的位变成0,因为除了1其他2的幂都是只有1位是1,所以如果这个1变成了0,结果就会变成0,也就是&运算后等于0就是2的幂
        return n >= 1 && (n & (n - 1)) == 0;
    }
}

提交代码后,执行用时1ms,时间击败100.00%的用户,内存消耗35.4MB,空间击败82.22%的用户。

运行结果
方法3

有没有想过还有更骚的方法?

俗话说,武功再高,也怕菜刀。这句话用在算法上就是,算法再牛,也怕暴力破解。

我们拍一拍自己的脑袋,去想一想,摸一摸,在整数范围内,2的幂一共多少个?

题目已经说了,整数的范围是:-2^31 <= n <= 2^31 - 1。

所以我们拍拍脑袋就可以摊牌了,答案就是从2的0次幂到2的30次幂。

写个java程序把所有的答案列举出来:

public class Main {

    public static void main(String[] args) {
        showAllTwoPower();
    }

    private static void showAllTwoPower() {
        int num = 1;

        for (int i = 0; i <= 30; ++i) {
            System.out.println("2的" + i + "次幂:" + num);
            num *= 2;
        }
    }

}

打印结果:

2的幂所有整数结果

所以解答代码为:

class Solution {
    public boolean isPowerOfTwo(int n) {
        // 暴力破解所有
        switch (n) {
            case 1:
            case 2:
            case 4:
            case 8:
            case 16:
            case 32:
            case 64:
            case 128:
            case 256:
            case 512:
            case 1024:
            case 2048:
            case 4096:
            case 8192:
            case 16384:
            case 32768:
            case 65536:
            case 131072:
            case 262144:
            case 524288:
            case 1048576:
            case 2097152:
            case 4194304:
            case 8388608:
            case 16777216:
            case 33554432:
            case 67108864:
            case 134217728:
            case 268435456:
            case 536870912:
            case 1073741824:
                return true;
        }

        return false;
    }
}

提交代码后,执行用时1ms,时间击败100.00%的用户,内存消耗35.1MB,空间击败99.41%的用户。

运行结果

骚不骚?

总结解题

掌握位运算,想多骚有多骚;三十六计,暴力破解为上计。

以上内容,纯属装逼

原文链接

原文链接:https://mp.weixin.qq.com/s/jKPueLPTUJD8gbnkipZEOw

你可能感兴趣的:(LeetCode刷题-2的幂)