接上文leetcode - 位运算题目汇总(上),继续来切leetcode中Bit Manipulation下的题目。

Bitwise AND of Numbers Range


给出一个范围,[m, n](0 <= m <= n <= 2147483647),返回这些数字的与运算结果。

直接逐个做与运算,TLE,我们得发现高效解法。

我们把[0, 15]用二进制码表示出来:

0 0 0 0
0 0 0 1
0 0 1 0
0 0 1 1
0 1 0 0
0 1 0 1
0 1 1 0
0 1 1 1
1 0 0 0
1 0 0 1
1 0 1 0
1 0 1 1
1 1 0 0
1 1 0 1
1 1 1 0
1 1 1 1

仔细看,几个连续的二进制码肯定会有相同的前缀(前缀长度可能为0),比如以下的二进制码相同的前缀就是1 0:

1 0 0 0
1 0 0 1
1 0 1 0
1 0 1 1

除了相同的前缀外,将之后的各位置为0即为所求:1 0 0 0,也就是8。如何求解这个相同前缀?只需要m和n同时右移,直到两数相等为止:

/**
 * @param {number} m
 * @param {number} n
 * @return {number}
 */
var rangeBitwiseAnd = function(m, n) {
  if (m === n)
    return m;

  var tmp = rangeBitwiseAnd(m >> 1, n >> 1);
  return tmp << 1;
};

还有一种更巧妙的方法,将n的最右边的 1 bit 置为0,直到值不大于m即可:

/**
 * @param {number} m
 * @param {number} n
 * @return {number}
 */
var rangeBitwiseAnd = function(m, n) {
  while (m < n)
    n = n & (n - 1);
  return n;
};

Repeated DNA Sequences


给你一串字符串表示DNA,输出重复的子串。

Given s = "AAAAACCCCCAAAAACCCCCCAAAAAGGGTTT",

Return:
["AAAAACCCCC", "CCCCCAAAAA"].

直接用JavaScript的对象哈希字符串,提交,MLE:

var findRepeatedDnaSequences = function(s) {
  var hash = {}
    , ans = 0;

  for (var i = 0, len = s.length; i < len; i++) {
    var str = s.substr(i, 10);
    if (str.length < 10) break;
    if (!hash[str])
      hash[str] = 1;
    else if (hash[str] === 1)
      hash[str]++, ans++;
  }

  return ans;
};

这题的关键是如何哈希,幸运的是JavaScript虽然没有C++那样强大的stl,但是也有Set,我们用set进行哈希,AC:

var findRepeatedDnaSequences = function(s) {
  var hash = new Set()
    , hash_ans = new Set()
    , ans = [];

  for (var i = 0, len = s.length; i < len; i++) {
    var str = s.substr(i, 10);
    if (str.length < 10) break;
    if (!hash.has(str))
      hash.add(str);
    else {
      if (!hash_ans.has(str)) {
        hash_ans.add(str);
        ans.push(str);
      }
    }
  }

  return ans;
};

但是好像没有说到位运算啊!我们思考下如何用数字哈希代替字符串哈希以减少内存消耗。

如果只有两种字符,我们便可以用0和1分别代替字符,组成一个二进制码,然后用一个整数代替这个二进制码完成哈希。但是不幸的是,现在有四个字符,如何?4进制?4进制的确是个好办法,但是操作起来不方便,我们可以用两位二进制码代替一位四进制码,比如我们分别用0 1 2 3表示A C G T,用两位的二进制码00 01 10 11代替0 1 2 3

var findRepeatedDnaSequences = function(s) {
  var map = []
    , hash = new Array(0xfffff)
    , ans = [];

  map['A'] = 0, map['C'] = 1, map['G'] = 2, map['T'] = 3;

  var tmp = 0;
  for (var i = 0, len = s.length; i < len; i++) {
    tmp = tmp << 2 | map[s[i]];
    if (i < 9) continue;
    if (i > 9) tmp = tmp & 0xfffff;

    if (!hash[tmp])
      hash[tmp] = 1;
    else if (hash[tmp] === 1)
      hash[tmp]++, ans.push(s.substring(i - 9, i + 1));
  }

  return ans;
};

不幸的是,又是MLE...这里不得不嗔怪下JavaScript对象的“吝啬”,稍微内存大搞大点,就MLE了,其实也就开了1048575大的数组。还好我们有set..

var findRepeatedDnaSequences = function(s) {
  var map = []
    , hash = new Set()
    , hash_ans = new Set()
    , ans = [];

  map['A'] = 0, map['C'] = 1, map['G'] = 2, map['T'] = 3;

  var tmp = 0;
  for (var i = 0, len = s.length; i < len; i++) {
    tmp = tmp << 2 | map[s[i]];
    if (i < 9) continue;
    if (i > 9) tmp = tmp & 0xfffff;

    if (!hash.has(tmp))
      hash.add(tmp);
    else {
      if (!hash_ans.has(tmp)) {
        hash_ans.add(tmp);
        ans.push(s.substring(i - 9, i + 1));
      }
    }
  }

  return ans;
};

144ms beats 100% JavaScript submissions

其他


其他题目我在别的文章中都有所涉及:

  1. Single Number【位运算经典应用】 寻找那个唯一的数
  2. Single Number II(同上)
  3. Single Number III(同上)
  4. Number of 1 BitsJavaScript 位运算总结&拾遗
  5. Reverse Bits【位运算经典应用】 求二进制逆序

leetcode - 位运算题目汇总(下)的更多相关文章

  1. leetcode - 位运算题目汇总(上)

    最近在看位运算的知识,十分感叹于位运算的博大精深,正好leetcode有 Bit Manipulation 的专题,正好拿来练练手. Subsets 给出一个由不同的数字组成的数组,枚举它的子数组(子 ...

  2. leetcode top 100 题目汇总

    首先表达我对leetcode网站的感谢,与高校的OJ系统相比,leetcode上面的题目更贴近工作的需要,而且支持的语言广泛.对于一些比较困难的题目,可以从讨论区中学习别人的思路,这一点很方便. 经过 ...

  3. All LeetCode Questions List 题目汇总

    All LeetCode Questions List(Part of Answers, still updating) 题目汇总及部分答案(持续更新中) Leetcode problems clas ...

  4. 78 leetCode 位运算解法

    按照自己的理解题目,数组内所有的组合:假如[1,2,3,4]看成1111到0000里面的排列组合,取位运算. vector<vector > subsets(vector&nums ...

  5. leetcode.位运算.136只出现一次的元素-Java

    1. 具体题目 给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次.找出那个只出现了一次的元素. 说明:你的算法应该具有线性时间复杂度. 你可以不使用额外空间来实现吗? 示例 1 ...

  6. BitMap - leetcode [位运算]

    136. Single Number 因为A XOR A = 0,且XOR运算是可交换的,于是,对于实例{2,1,4,5,2,4,1}就会有这样的结果: (2^1^4^5^2^4^1) => ( ...

  7. leetcode 位运算异或

    1. 只出现一次的数字(136) 异或的性质总结: 相异为1,相同为0: a ^ a = 0; 0 ^ a = a; 如果 a ^ b = c 成立,那么a ^ c = b 与 b ^ c = a 均 ...

  8. JavaScript 位运算总结&拾遗

    最近补充了一些位运算的知识,深感位运算的博大精深,此文作为这个系列的总结篇,在此回顾下所学的位运算知识和应用,同时也补充下前文中没有提到的一些位运算知识. 把一个数变为大于等于该数的最小的2的幂 一个 ...

  9. 位运算总结&拾遗

    JavaScript 位运算总结&拾遗 最近补充了一些位运算的知识,深感位运算的博大精深,此文作为这个系列的总结篇,在此回顾下所学的位运算知识和应用,同时也补充下前文中没有提到的一些位运算知识 ...

随机推荐

  1. Mysql 创建用户 授权

    一, 创建用户: 命令:CREATE USER 'username'@'host' IDENTIFIED BY 'password'; 说明:username - 你将创建的用户名, host - 指 ...

  2. my_ls

    #include<stdio.h> #include<dirent.h> #include<string.h> #include<sys/types.h> ...

  3. 仿哔哩哔哩应用客户端Android版源码项目

    这是一款高仿哔哩哔哩安卓客户端,跟官方网的差不多吧,界面也几乎是一样的,应用里面也加了一些弹出广告,大家可以参考一下吧,安装测试包在源码文件那里,大家可以多多参考一下. 哔哩哔哩弹幕网是国内知名的弹幕 ...

  4. Linux 下子线程的 pthread_cleanup_push() 和 pthread_cleanup_pop() 研究

    线程退出前可能有一些清理工作,但是这部分代码又不会放到线程主体部分,就需要挂接一个或者几个线程“清洁工”来做这部分事情.需要这对兄弟: #include<pthread.h> void p ...

  5. Ganglia安装扩容

    现有的环境中Hbase集群的机器需要安装ganglia,遂采取了以下步骤. 查看机器的信息, uname –a cat /etc/issue 查看当前环境是x86的,安装的是red hat 6.4 之 ...

  6. web报表工具FineReport常用函数的用法总结(报表函数)

    说明:本次总结中,凡是以tableName或viewName作为参数因子的.函数在调用的时候均按照先从私有数据源中查找,然后再从公有数据源中查找的顺序. CLASS CLASS(object):返回o ...

  7. 用FineReport做的共建共享填报系统

    一.应用背景 随着信息技术的不断发展,快速开发出适合用户业务需求发展的填报报表是势在必然的,因此在不断的研究和分析下针对这一业务特点制作了此报表系统,以使不同开发商之间共建共享数据进行填报和统计分析的 ...

  8. ovirt-engine安装

    一.安装 1.更新系统 原来是centos4.5 #yum update 升级后到6.7版本. [root@localhost ~]# cat /etc/redhat-release CentOS r ...

  9. Java修饰符public,private,protected及默认的区别

    Java中访问修饰符public.private.protecte.default的意义讲解:public(接口访问权限): Java语言中访问限制最宽的修饰符,一般称之为“公共的”.被其修饰的类.属 ...

  10. 用jsmooth + inno生成exe并制作简单安装包

    思路: 先由 Jsmooth把jar和相关资源打包生成exe,再由Inno把exe和资源文件打成安装包 一  Jsmooth 1 下载 安装 Jsmooth   地址:jsmooth.sourcefo ...