算法篇:位运算进阶(二)

算法

转换成前面算法篇:位运算异或的使用(一)中,两位相同的数异或为0,转换成3位数的"异或"操作位0,也就是说我们需要实现同一个bit位的3个1,操作为0就可以,将问题转换为对如何实现同一bit位的三个数的操作a?b?c =0的运算。

因为两位数的异或操作,是同一个bit位的两个数的加法,忽略进位的情况,换种说法就是两数相加对2取余数。所以三个相同的数的a?b?c = 0的操作就变成了,三位数操作对3取余了。

同样的道理,4位数,n位数都可以采用这一个算法来实现。

题目:只出现一次的数字 II

https://leetcode-cn.com/problems/single-number-ii/

算法1:数学公式

这个题目可以转换成下面的公式:2c = 3(a+b+c)-sum,

这里的a,b,c是数组中出现的元素,c是出现了一次的数,a,b都是出现了3次的数。

sum表示的是:数组里面所有数的和。

备注:同样的算法,也适合数组里面有n次重复的数组,和1个不重复的数 ,公式为:n(a+b+c)-sum = (n-1)c

代码实现:

func singleNumber(nums []int) int {
    m := make(map[int]int)
     s1,s2 := 0,0
    for _,n:=range nums {
        _,ok := m[n]
        if !ok {
            m[n] = n
        }
        s1 += n
    }
   
    for _,v:= range m {
        s2 += v
    }
    res := (3*s2-s1)/2
    return res
}
// 算法:假设3个a,b,一个c: 公式: 3(a+b+c) - sum = 2c

执行结果:

算法2: 采用位运算

指导思路是:转换成前面算法篇:位运算异或的使用(一)中,两位相同的数异或为0,转换成3位数的"异或"操作位0,也就是说我们需要实现同一个bit位的3个1,操作为0就可以,将问题转换为对如何实现同一bit位的三个数的操作a?b?c =0的运算。

因为两位数的操作采用的是异或,也就是 :

1^1 = 0 
1^0 = 1
0^1 = 1
0^0 =0
这其实是同一个bit位的两个数的加法,忽略进位的情况,换种说法就是两数相加对2取余数。

参考:算法篇:位运算基本操作

所以三个相同的数的a?b?c = 0的操作就变成了,三位数操作对3取余了。

代码实现:

func singleNumber(nums []int) int {
    num,res := 0,0
    for i:=0;i<64;i++ {
        // 每一bit位都需要计算,所以这里要做清0处理
        num = 0
        for _, n := range nums {
            // 通过右移,来计算num的数量
            num += (n>>i)&1
        }
        // 将计算结果还原到对应的bit位
        res |= (num)%3<<i
    }
    return res
}

执行结果:



正在收集公众号后续整理内容,截止到本周末,欢迎大家投票:

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值