leetcode - 位运算题目汇总(下)
接上文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
其他
其他题目我在别的文章中都有所涉及:
- Single Number (【位运算经典应用】 寻找那个唯一的数)
- Single Number II(同上)
- Single Number III(同上)
- Number of 1 Bits(JavaScript 位运算总结&拾遗)
- Reverse Bits(【位运算经典应用】 求二进制逆序)
leetcode - 位运算题目汇总(下)的更多相关文章
- leetcode - 位运算题目汇总(上)
最近在看位运算的知识,十分感叹于位运算的博大精深,正好leetcode有 Bit Manipulation 的专题,正好拿来练练手. Subsets 给出一个由不同的数字组成的数组,枚举它的子数组(子 ...
- leetcode top 100 题目汇总
首先表达我对leetcode网站的感谢,与高校的OJ系统相比,leetcode上面的题目更贴近工作的需要,而且支持的语言广泛.对于一些比较困难的题目,可以从讨论区中学习别人的思路,这一点很方便. 经过 ...
- All LeetCode Questions List 题目汇总
All LeetCode Questions List(Part of Answers, still updating) 题目汇总及部分答案(持续更新中) Leetcode problems clas ...
- 78 leetCode 位运算解法
按照自己的理解题目,数组内所有的组合:假如[1,2,3,4]看成1111到0000里面的排列组合,取位运算. vector<vector > subsets(vector&nums ...
- leetcode.位运算.136只出现一次的元素-Java
1. 具体题目 给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次.找出那个只出现了一次的元素. 说明:你的算法应该具有线性时间复杂度. 你可以不使用额外空间来实现吗? 示例 1 ...
- BitMap - leetcode [位运算]
136. Single Number 因为A XOR A = 0,且XOR运算是可交换的,于是,对于实例{2,1,4,5,2,4,1}就会有这样的结果: (2^1^4^5^2^4^1) => ( ...
- leetcode 位运算异或
1. 只出现一次的数字(136) 异或的性质总结: 相异为1,相同为0: a ^ a = 0; 0 ^ a = a; 如果 a ^ b = c 成立,那么a ^ c = b 与 b ^ c = a 均 ...
- JavaScript 位运算总结&拾遗
最近补充了一些位运算的知识,深感位运算的博大精深,此文作为这个系列的总结篇,在此回顾下所学的位运算知识和应用,同时也补充下前文中没有提到的一些位运算知识. 把一个数变为大于等于该数的最小的2的幂 一个 ...
- 位运算总结&拾遗
JavaScript 位运算总结&拾遗 最近补充了一些位运算的知识,深感位运算的博大精深,此文作为这个系列的总结篇,在此回顾下所学的位运算知识和应用,同时也补充下前文中没有提到的一些位运算知识 ...
随机推荐
- sysbench测试工具
sysbench简介 Sysbench是一个模块化的.跨平台.多线程基准测试工具,主要用于评估测试各种不同系统参数下的数据库负载情况.它主要包括以下几种方式的测试:cpu性能,磁盘io性能,线程调度性 ...
- 看看Parallel中高度封装的三个方法,Invoke,For和ForEach
说到.net中的并行编程,也许你的第一反应就是Task,确实Task是一个非常灵活的用于并行编程的一个专用类,不可否认越灵活的东西用起来就越 复杂,高度封装的东西用起来很简单,但是缺失了灵活性,这篇我 ...
- MemSQL分布式架构介绍(一)
最近在了解MemSQL架构,看了些官方文档,在这里做个记录,原文在这里:http://docs.memsql.com/latest/concepts/distributed_architecture/ ...
- CStdioFile CString 读写中文
TCHAR* old_locale = _tcsdup( _tsetlocale(LC_CTYPE,NULL) ); _tsetlocale( LC_CTYPE, _T("chs" ...
- 简易的GCC图形界面GCCUI
这个 GCCUI.EXE 是配合上一篇博文<用VC6开发嵌入式LINUX程序>说的:用VC6辅助开发LINUX程序的时候使用.把 gcc 编译器增加一个简易的图形界面,可以自动读取 vc6 ...
- shell脚本实现随机筛选
#!/bin/bash name=(val1 val2 val3 val4 ...) a=$() #以时间产生随机数向39取余得到0~38的值
- proteus 运行出错,用户名不可使用中文!
仿真的时候提示如图提示 cannot open ’c\user\小名\AppData\local\temp\LISA0089.sdf’ 系统用户名不能是中文! 解决办法:重新建立个账户,记得用英文命名 ...
- 中午游泳很海皮-linux&php
hi 中午又去游泳了,其实本来打算是昨天去的,谁知天公不作美,周一都下雨.今天其实也一样的,有点小雨,不过游得到泳,比什么都好 1.PHP&MySQL -----PHP内置MySQL函数学习( ...
- 求最大边/最小边的比值最小的路径 codevs 1001 舒适的路线
codevs 1001 舒适的路线 2006年 时间限制: 2 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description Z小镇是一个景色宜人 ...
- java 22 - 5 多线程之获取和设置线程对象的名称
如何获取线程对象的名称呢? public final String getName():获取线程的名称.如何设置线程对象的名称呢? public final void setName(String n ...