判断一个数是否为4的幂(多种解法)| 青训营笔记

154 阅读3分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第3天。

今天想讲一下我学到的判断一个数字是否为为4的幂的几种方法,可以体现代码优化的过程。

题目:判断一个数是否为4的幂(1是4的0次幂)

方法一: 常规思路,一个while循环,让num一直除以4,如果num取余4不是0,那返回false,直到num===1,返回true。
(不要忘记每次对输入类型进行转换,将其转换为数字类型。)

function isPowerOfFour(num) {
  num = parseInt(num);

  while(num > 1) {
    if(num % 4) return false;
    num /= 4;
  }
  return num === 1;
}

方法二: (位运算)用num & 0b11来判断num的二进制数后两位是不是0(因为4的幂的二进制编码一定是1000000,即1后面偶数个0),如果后两位都是0的话,那就让num右移两位,再进行下一轮while判断),直到num===1返回true。

function isPowerOfFour(num) {
  num = parseInt(num);

  while(num > 1) {
    if(num & 0b11) return false;
    num >>>=2;
  }
  return num === 1;
}

方法三: (位运算)这里有里三个判断条件,用这三个判断条件可以一次判断出num是否为4的幂。

  • num>0自不用说,num & (num-1)===0可以判断num是否是2的幂,即1后面多个0。
    一个正整数位与一个他减一的二进制数,会让这个正整数二进制中的1减少一个。
    例如:11110 & 11101 = 11100;
    11111 & 11110=11110
    10000 & 01111 = 00000
    (低位少了一个1)
    即我们知道了,如果想是4的幂,那对应的二进制数的偶数位上不能是1,比如10000,只能是从低到高奇数位上有一个1,后面全是0。
  • (num & 0xAAAAAAAAAAAAA) === 0 可以判断num对应的二进制数后面是不是1加偶数个0。
    用num位与一串1010101010可以判断出num是否偶数位上没有1。而0xAAAAAAAAAAA这个数是根据JS浮点数的位数决定的值。

这三个条件同时满足的话,可判断出num是否是4的幂。这是一个时间复杂度为O(1)的算法。比前面的方法要节省时间。

function isPowerOfFour(num){
  num = parseInt(num);
  
  return num > 0 &&
         (num & (num - 1)) === 0 &&
         (num & 0xAAAAAAAAAAAAA) === 0;
}

方法四: 既然是JS,可以使用正则表达式来判断。

JS中不检查输入类型,可以将输入直接转为二进制的字符串,比如16转为'10000',再用正则表达式匹配字符串是否是1后面跟偶数个0。是的话num即是4的幂。

function isPowerOfFour(num) {
  num = parseInt(num).toString(2);
  
  return /^1(?:00)*$/.test(num);
}

总结:本题需要注意的是每次对输入进行parseInt()转换成数字,以及追求时间复杂度更低的算法。