位运算

  1. 题目一
  2. 题目二
  3. 参考

涉及到位运算的数据结构与算法题。

题目一

该题很容易出现在各大厂的面试中,属于必须掌握的题型。

题目描述:

求 1 至 n 连续 n 个数的和。要求不能使用乘除法、for、while、if、else、switch、case 等关键字及条件判断语句(A?B:C)。
1 <= n <= 10000

解法一:
直接等差求和公式显然不行,因为包含乘除法。不行。吗?逻辑右移搞定!

代码:

// 套公式加位运算
function sumF(n) {
    return (Math.pow(n, 2) + n) >>> 1;  // 无符号右移,不过这里有没有符号都一样,因为 n 是正整数
}

解法二:

递归要有终止条件,需要 if 判断,也不行。吗?可以使用逻辑判断运算符绕过!嘻嘻

为了对比,先写一个无限制的递归版吧:

// 正常递归版
function sumN(n) {
    if (n <= 0) {
        return 0;
    }
    return n + sumN(n - 1);
}

使用逻辑或运算:

// 使用逻辑运算
function sumH(n) {
    return n > 0 && (n + (sumH(n - 1)));
}

这里利用了 JavaScript 逻辑运算的特殊性。即逻辑运算返回值保持表达式原值!

题目二

给定一个整数 n,编写一个函数来判断它是否是 2 的幂次方。
$-2^{31} <= n <= 2^{31} - 1$
进阶:你能够不使用循环 / 递归解决此问题吗?

解法一:
利用位运算中的按位或运算。2 的幂都是首 1 全 0 的二进制。
while 循环加位运算:

function is2(n) {
    if (n <= 0) {
        return false;
    }
    while (true) {
        if (n === 1) {
            return true;
        }
        if (n & 1 === 1) {
            // 说明 n 的二进制表示中最后一个二进制位是 1
            return false;
        }
        n = n >>> 1;
    }
}

解法二:
利用 2 的幂的二进制,减去一,是全 1 的二进制。

var isPowerOfTwo = function(n) {
    return n > 0 && (n & (n-1)) === 0;
};

参考

  • 和小浩学算法. pdf

转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论。
我的空间