• leetcode


    最近在看位运算的知识,十分感叹于位运算的博大精深,正好leetcode有 Bit Manipulation 的专题,正好拿来练练手。

    Subsets###


    给出一个由不同的数字组成的数组,枚举它的子数组(子集)。

    这道题我之前用递归解过,而且效率还不错(beat 83.33%),解法如下不加详述了:

    /**
     * @param {number[]} nums
     * @return {number[][]}
     */
    
    var ans, res, len;
    
    function dfs(index, nums) {
      ans.push(res.concat());
    
      for (var i = index; i < len; i++) {
        res.push(nums[i]);
        dfs(i + 1, nums);
        res.pop();
      }
    }
    
    var subsets = function(nums) {
      nums.sort(function(a, b) {
        return a - b;
      });
    
      ans = [],
      res = [],
      len = nums.length;
    
      dfs(0, nums);
    
      return ans;
    };
    

    如果用位运算解,这是一道经典的枚举子集

    比如我们有数组[1, 2, 3],还是要用到标志位的概念,全集为1 1 1,全集表示都取,它的子集有1 0 11 1 01 0 0等等,我们通过枚举子集,然后再通过子集获取原来数组的元素即可。

    比如子集 1 0 1,我们可以依次获取最右边的1,然后根据获取的1的大小判断数组元素的index位置从而获取数组,之后把该1置为0即可。

    /**
    * @param {number[]} nums
    * @return {number[][]}
    */
    var subsets = function(nums) {
      nums.sort(function(a, b) {
        return a - b;
      });
    
      var all = (1 << nums.length) - 1
        , ans = [];
    
      // 枚举子集
      for (i = all; i; i = (i - 1) & all) {
        var tmp = i
          , res = [];
    
        while (tmp) {
          var rightMostOne = tmp & (-tmp)
            , index = Math.log(rightMostOne) / Math.log(2);
    
          res.push(nums[index]);
          tmp = tmp & (tmp - 1);
        }
    
        ans.push(res);
      }
    
      // 子集的枚举没有0,所以要special insert
      ans.push([]);
      return ans;
    };
    

    Power of Two###


    判断一个数是不是2的幂。如果一个数是2的幂,那么该数与上该数-1为0。我们以8举例:

    1 0 0 0
    0 1 1 1
    

    很明显,上面两数做与运算的结果是0。但是有个特殊的情况是,0 & (0 - 1) === 0,所以我们还得判断该数为正。

    /**
     * @param {number} n
     * @return {boolean}
     */
    var isPowerOfTwo = function(n) {
      return (!(n & (n - 1)) && n > 0);
    };
    

    这里加强下,如果知道某数是2的幂,求解这个指数值。即Math.pow(2, x) = n ,求x的值。

    也很简单,用个log的换底公式(其实没有涉及位运算):

    return Math.log(n) / Math.IN2;
    

    Missing Number###


    给出一个0~n组成的数组[0, 1, 2, 3 ... n],从中随即去掉一个数字,给你新的数组,求解被去掉的数字。比如给你[0, 1, 3],返回2

    这题涉及^运算的性质:

    // if 
    a ^ b = c;
    
    // then
    a ^ c = b;
    b ^ c = a;
    

    解法也就呼之欲出了。还是假设数组[0, 1, 3],我们可以知道n为3(等于数组长度),从而可以计算出0 ^ 1 ^ 2 ^ 3的值,我们把它赋值给c;然后我们计算所给数组的元素的异或值,赋值给a,假设被舍弃的元素为b,我们可以得到如下等式:

    a ^ b = c;
    

    根据前边所讲:

    b = a ^ c;
    

    完整代码:

    /**
     * @param {number} n
     * @return {boolean}
     */
    /**
     * @param {number[]} nums
     * @return {number}
     */
    var missingNumber = function(nums) {
      var a = nums.reduce(function(pre, item) {
        return pre ^ item;
      });
    
      var b = nums.reduce(function(pre, item, index) {
        return pre ^ index;
      }, nums.length);
    
      return a ^ b;
    };
  • 相关阅读:
    C++中的空类,编译器默认可以产生哪些成员函数
    野指针(Wild pointer)和悬垂指针(dangling pointer)
    WHY C++ ?(by Herb Sutter) & C++17 standard
    mapreduce 多路输出
    stdout 编码 vim 删除左边,右边
    积累碎片shell
    python logging模块
    shell 流程控制
    shell 变量
    时间管理法则
  • 原文地址:https://www.cnblogs.com/lessfish/p/4796940.html
Copyright © 2020-2023  润新知