位运算符有
- &
按位与
如果两个相应的二进制位都为1,则该位的结果值为1,否则为0 - |
按位或
两个相应的二进制位中只要有一个为1,该位的结果值为1 - ^
按位异或
若参加运算的两个二进制位值相同则为0,否则为1 - ~
取反
~是一元运算符,用来对一个二进制数按位取反,即将0变1,将1 - <<
左移
用来将一个数的各二进制位全部左移N位,右补0 - >>
右移
将一个数的各二进制位右移N位,移到右端的低位被舍弃,对于无符号数, 高位补0(正数)或1(负数) - >>>
右移
将一个数的各二进制位右移N位,移到右端的低位被舍弃,对于无符号数, 高位补0
先引入一些别人对位运算的总结:
4.m的n次方
//时间复杂度近为 O(logn),而且看起来很牛逼。
int pow(int n){
int sum = 1;
int tmp = m;
while(n != 0){
if(n & 1 == 1){
sum *= tmp;
}
tmp *= tmp;
n = n >> 1;
}
return sum;
}
————————————————
版权声明:本文为CSDN博主「帅地」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/m0_37907797/article/details/103120886
今天遇到的题目是这样的(就是上面大佬总结的第3个方法的升级版):
class Solution {
public int[] singleNumber(int[] nums) {
int xorsum = 0,a=0,b=0;
for (int num : nums) {
xorsum ^= num;
}
int div=1;
while((xorsum & div)==0){
div=div<<1;
}
for(int i=0;i<nums.length;i++){
if((nums[i] & div)==0){
a=a ^nums[i];
}else{
b=b^nums[i];
}
}
return new int[]{a, b};
}
}
知识基础:a ^ b ^ b=a,且满足结合律和分配律(b ^ a ^ b=a),故相同的数是可以直接消除的。很容易得到最后两个不同数字的^(异或)结果。所以关键是怎么区分他们呢?
先说实例:3(0011),5(0101)
3^5=0110(6),我就可以用倒数第二位的那个1作为3跟5的区别对他们进行不同的分组,用0010和3(0011)做&与运算,得到的是0010(非0)。用0010和5(0101)做&与运算,得到的是0000(为0)。
再说道理:两个数的异或值中,为1的那几位数就是这两个数的不同点,只要找到是第几位为1,然后用这个位数跟这两个数进行与运算,得到的值一定不同。
- 将数组每个值都进行异或运算,相同的为0,最后得到的就是那两个独立的值的异或结果记为xorsum。
- 数字1(div)的二进制为0001,用它末尾的那个1与xorsum进行&与运算,得到为0,说明xorsum的最后一位为0,我们要找到xorsum中为1的那一位,所以让数字1进行左移<<,重复判断得到div(例如可能是0010),用div这个数与数组元素进行与运算,就可以把需要找的那两个数分开为两组了。
可能说的不是太清楚,但我真的尽力了,只能说我自己心里清楚了,位运算确实有点东西。我第一想法其实是用HushMap做的,但空间复杂度有点高。
最后有个更难理解的题,:
class Solution {
public int singleNumber(int[] nums) {
int ans = 0;
for (int i = 0; i < 32; ++i) {
int total = 0;
for (int num: nums) {
total += ((num >> i) & 1);
}
if (total % 3 != 0) {
ans |= (1 << i);
}
}
return ans;
}
}
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/WGki4K/solution/zhi-chu-xian-yi-ci-de-shu-zi-by-leetcode-0vrt/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
我感觉还是HushMap更好理解,哭唧唧
class Solution {
public int singleNumber(int[] nums) {
Map<Integer, Integer> freq = new HashMap<Integer, Integer>();
for (int num : nums) {
freq.put(num, freq.getOrDefault(num, 0) + 1);
}
int ans = 0;
for (Map.Entry<Integer, Integer> entry : freq.entrySet()) {
int num = entry.getKey(), occ = entry.getValue();
if (occ == 1) {
ans = num;
break;
}
}
return ans;
}
}
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/WGki4K/solution/zhi-chu-xian-yi-ci-de-shu-zi-by-leetcode-0vrt/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。