LeetCode解题中位运算的运用
位运算是我最近才开始重视的东西,因为在LeetCode上面刷题的时候发现很多题目使用位运算会快很多。位运算的使用包含着许多技巧(详细可以参考http://blog.csdn.net/zmazon/article/details/8262185),但我仅仅在大一学C语言入门的时候接触过,很多东西都不了解,因此我在这篇文章里面稍微总结一下我在LeetCode遇到的关于位运算的题目,当然仅仅只是一部分,因此这篇文章可能会在我每次遇到位运算的题目时更新一下。
首先要回忆一下有哪些位运算的操作:
| 按位与 | a&b |
| 按位或 | a|b |
| 按位异或 | a^b |
| 按位取反 | ~a |
| 左移 | a<<b |
| 右移 |
a>>b |
然后就是LeetCode上面的题目了:
(1)136. Single Number(https://leetcode.com/problems/single-number/description/)
给定一个数组,数组中的每一个值在数组里面都出现了2次,只有一个值只出现了1次,要求我们把它找出来。
一般的思路肯定是开辟一块空间来操作(类似于桶)或者排序然后查找,但题目里面有这样一个提示“Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?”,“linear runtime complexity”,即要求在O(n)的时间复杂度里面完成,先排序的方法肯定不行了;“without using extra memory”,另一种想法也抹杀掉。
在这种情况下,我们可以使用位运算中的异或来帮助我们解题。(我发现有特别提示的题目一般都会有“投机取巧”的解题方法,比如这一题的位运算)我们可以发现,一个数与它自己本身进行异或操作,结果肯定为0;0和一个数做异或操作,结果肯定为这个数,利用这一点,我们就可以很好地在O(n)的时间复杂度里面解决问题:
class Solution {
public:
int singleNumber(vector<int>& nums) {
int res = 0;
for (int i = 0; i < nums.size(); i++) {
res ^= nums[i];
}
return res;
}
};
(2)268. Missing Number(https://leetcode.com/problems/missing-number/description/)
这一题给出一个值连续的数组,只不过在中间抽掉了一个值,让我们找出来。我们可以先根据给出的数组大小求出本来的结果(即没有抽掉数的总和),然后求出现在的总和,两者相减,就可以得出结果。这是一种方法:
class Solution {
public:
int missingNumber(vector<int>& nums) {
int sum = ;
for (int i = ; i < nums.size(); i++) {
sum += nums[i];
}
int actual_sum = nums.size() * (nums.size() + ) /;
return actual_sum - sum;
}
};
当然还有用位运算解决的方法,也是异或,原理也是上面一题的原理。只不过为了要用到“一个数与它自己本身进行异或操作”这一点,我们需要在原基础上增加一个变量,使一个数能出现两次:
class Solution {
public:
int missingNumber(vector<int>& nums) {
int res = ;
int temp = ;
for (int i = ; i < nums.size(); i++) {
res ^= nums[i] ^ temp;
temp++;
}
return res;
}
};
从上面两题中,我们是不是总结出一点呢?当题目给出一堆数,其中的一个数的数量和其他数不同,要求把它找出来,我们可以考虑使用位运算中的异或操作解决。
(3)191. Number of 1 Bits(https://leetcode.com/problems/number-of-1-bits/description/)
这一题要求一个数的二进制数中有几个1。我们只需要将这个数不断地右移,然后和与1按位相与,直到这个数为0即可。假如一个数的最右一位为0,与1相与为0;为1,与1相与为1。代码如下:
class Solution {
public:
int hammingWeight(uint32_t n) {
int res = ;
while (n) {
res += (n & );
n = n >> ;
}
return res;
}
};
(4)求一个数是否2的幂
这道题在我的另一篇博客里面有讨论,不展开了。
http://www.cnblogs.com/fengziwei/p/7570885.html
(5)371. Sum of Two Integers(https://leetcode.com/problems/sum-of-two-integers/description/)
这道题就是用位运算实现正整数加法,投机取巧也能过,但这就没意思了。
加法的实现,无非就是当前位相加,然后考虑进位即可。不考虑进位,0+0为0,1+0为1,1+1为0,这是异或的操作。然后考虑进位,只有1+1的时候才需要进位,因此可以先将当前位相与,再将结果左移1位。因为不能用加法,所以要利用循环,当没有进位的时候结束。具体代码如下:
class Solution {
public:
int getSum(int a, int b) {
int res = a ^ b;
int temp = (a & b) << ;
while (temp) {
cout << res << endl;
cout << temp << endl;
int copy = res;
res = res ^ temp;
temp = (copy & temp) << ;
}
return res;
}
};
(6)461. Hamming Distance(https://leetcode.com/problems/hamming-distance/description/)
class Solution {
public:
int hammingDistance(int x, int y) {
int temp = x ^ y;
int res = ;
while (temp) {
res += temp & ;
temp >>= ;
}
return res;
}
};
未完待续。。。。。。
LeetCode解题中位运算的运用的更多相关文章
- js中位运算的运用
原文:js中位运算的运用 我们可能很少在编程中用位运算,如果没深入学习,可能也很难理解.平时的数值运算,其实是要先转换成二进制再进行运算的,而位运算就是直接进行二进制运算,所以位运算的执行效率肯定是更 ...
- LeetCode - 136. Single Number - ( C++ ) - 解题报告 - 位运算思路 xor
1.题目大意 Given an array of integers, every element appears twice except for one. Find that single one. ...
- LeetCode编程训练 - 位运算(Bit Manipulation)
位运算基础 说到与(&).或(|).非(~).异或(^).位移等位运算,就得说到位运算的各种奇淫巧技,下面分运算符说明. 1. 与(&) 计算式 a&b,a.b各位中同为 1 ...
- C#LeetCode刷题-位运算
位运算篇 # 题名 刷题 通过率 难度 78 子集 67.2% 中等 136 只出现一次的数字 C#LeetCode刷题之#136-只出现一次的数字(Single Number) 53.5% 简单 ...
- [LeetCode]78. 子集(位运算;回溯法待做)
题目 给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集). 说明:解集不能包含重复的子集. 示例: 输入: nums = [1,2,3] 输出: [ [3], [1], ...
- java中位运算
1byte(字节)=8bit(比特) 1 0 0 0 0 0 0 0 1 2进制的1的原码 反码 补码 0 0 0 0 0 0 0 0 2进制的0的原码 反码 补码 -1 1 0 0 0 0 ...
- C++中位运算
简介 1 位逻辑运算符: & (位 “与”) and ----------------- 2个都为1 才是1-----------0^0 = 0 , 0^1 = 0, 1^0 = 0 ...
- java中位运算和移位运算详解
一.位运算 (1)按 位 与 & 如果两个相应的二进制形式的对应的位数都为1,则结果为1,记为同1为1,否则为0.首先我们看一下对正数的运算 分别看一下正数和负数的具体运算步骤 ...
- Java实现 LeetCode 1111 有效括号的嵌套深度(阅读理解题,位运算)
1111. 有效括号的嵌套深度 有效括号字符串 定义:对于每个左括号,都能找到与之对应的右括号,反之亦然.详情参见题末「有效括号字符串」部分. 嵌套深度 depth 定义:即有效括号字符串嵌套的层数, ...
随机推荐
- Javascript是单线程的深入分析(转)
http://www.cnblogs.com/Mainz/p/3552717.html
- Jmeter之接口测试
最近才入职新公司,好几天没有写博客了,经过一个朋友提醒,刚刚好觉得用Jmeter来做接口测试真的是再好不过了.下面就详细讲解下这两天我利用Jmeter做的接口测试. [安装Jmeter] 详细见博文: ...
- 简述C/C++调用lua中实现的自定义函数
1.首先说下目的,为什么要这么做 ? 正式项目中,希望主程序尽量不做修改,于是使用C/C++完成功能的主干(即不需要经常变动的部分)用lua这类轻量级的解释性语言实现一些存在不确定性的功能逻辑:所以, ...
- MySQL存储引擎中的MyISAM和InnoDB区别
MyISAM是MySQL的默认数据库引擎(5.5版之前),由早期的ISAM(Indexed Sequential Access Method:有索引的顺序访问方法)所改良.虽然性能极佳,但却有一个缺点 ...
- Varnish后端主机的健康状态检查
author:JevonWei 版权声明:原创作品 配置后端主机的Health Check 环境 Varnish 192.168.198.139 图片服务端 192.168.198.120 程序服务端 ...
- Kafka中操作topic时 Error:Failed to parse the broker info from zookeeper
Kafka中操作topic时 Error: Failed to parse the broker info from zookeeper 1.问题描述 2.问题原因 kafka在启动后 ...
- svn status详解
svn 是在提交前查看本地文本和版本库里面的文件的区别.返回值有许多种具体含义如下: [url=] L abc.c # svn已经在.svn目录锁定了abc.c M ...
- java 运行时常量、编译时常量、静态块执行顺序
详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt223 常量是程序运行时恒定不变的量,许多程序设计语言都有某种方法,向编译器告 ...
- 字符编码笔记:ASCII,Unicode和UT…
字符编码笔记:ASCII,Unicode和UTF-8 今天中午,我突然想搞清楚Unicode和UTF-8之间的关系,于是就开始在网上查资料. 结果,这个问题比我想象的复杂,从午饭后一直看到晚上9点,才 ...
- MITNIK ATTACK
Https 443 http 80 TCP/IP 协议栈:将数据封装包头 传输层报头 Ack回复确认位 FIN结束位 SIN 开始位 RST 重置位 Seq 序号位 网络层报头 目的地址 原地址 报文 ...