算法记录(3)位运算

这篇博客探讨了如何利用位运算优化算法,通过与(&)和异或(^)操作实现空间复杂度为O(1)的解决方案。对于计算整数二进制表示中1的个数,可以使用n与(n-1)的&运算;在寻找数组中只出现一次的数字时,利用异或的性质找到唯一值。位运算是解决问题的巧妙工具,需要更多实践来熟悉和掌握。
摘要由CSDN通过智能技术生成

前言
最近在刷牛客的剑指offer和leetcode,刷的过程中会遇到各种各样的算法,用此系列贴记录下来。


位运算属实是奇妙方法,这次碰到的两题用位运算都可以把空间复杂度降到O(1)。
一共是两种方法,分别是&(与)另一种是^(异或)。
先来说&
题目描述
输入一个整数 n ,输出该数32位二进制表示中1的个数。其中负数用补码表示。
用暴力就是把n转化成二进制,然后数里面1的个数就好了
负数就相对麻烦一点,涉及到int的临界值问题

&运算:
当一个数n与(n-1)做&运算的时候,会消除掉最右边的一个1
0110&0101=0100

这样一来,用了几次&运算就说明它有几个1了
代码

class Solution {
public:
     int  NumberOf1(int n) {
         int num=0;
         while(n){
             num++;
             n=n&(n-1);
         }
         return num;
     }
};

11行代码解决了,短小精悍。


^异或
leetcode136:只出现一次的数字
题目描述
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
示例 1:

输入: [2,2,1]
输出: 1
示例 2:

输入: [4,1,2,1,2]
输出: 4

重复出现的题我下意识就会用哈希表,表里没有的加进去,有的删了,最后剩下的就是出现一次的。
代码:

class Solution {
public:
    int singleNumber(vector<int>& nums) {
        set<int> ans;
        for(auto i:nums){
            if(ans.count(i)==0){
                ans.insert(i);
            }
            else
            ans.erase(i);
        }
        int an;
        for(auto i:ans){
            an=i;
        }
        return an;
    }
};

然后看官方解答,发现官方用的异或,属实太妙了

0^a=a
a^a=0
满足交换律和结合律(这一点很重要,如果这一条不成立,这题就不能这么算)
那么用0去依次异或整个数组,剩下来的就是那个只出现一次的数
整个运算里所有的成双的数字都会变成0(交换律和结合律),最后只会剩下单独的数字
代码:

class Solution {
public:
    int singleNumber(vector<int>& nums) {
        int temp=0;
        for(auto i:nums){
            temp^=i;
        }
        return temp;
    }
};

位运算用的少,也不是很熟。在某些情况下有很妙的作用,平时还是要多积累,肚子里有货才能有骚操作。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值