位运算的几种应用

例1:不借助临时变量,交换两个数的值

思路:通过异或,先求出两个变量的不同的位

var a = 10
var b = 8

a = a ^ b
b = a ^ b
a = a ^ b

例2:求一个UInt二进制数中1的个数

思路:比如一个 1011 0100 这个二进制数,先用 1(0000 0001)和它做"与"操作,如果结果为 1,说明在最右边的这一位是 1,继续把 1 左移 1 位重复比较

func getCountOfOne(num: UInt) -> UInt {
    var count: UInt = 0
    var temp = num
    var loopCount = 0
    while temp != 0 {
        count += (temp & 1)
        temp = (temp >> 1)
        loopCount += 1
    }
    print("loop1 count: \(loopCount)")
    return count
}

上述算法有一个可以优化的地方,当有这样一个数 1100 0000,如果还是从最右边往左判断的话,有大量的 0 是没有必要的,我们可以从左边开始,让 num 和 num-1 这两个数做"与"运算,如果结果为 0,则说明这个数后续已经没有 1 了,反之继续比较

func getCountOfOne2(num: UInt) -> UInt {
    var count: UInt = 0
    var temp = num
    var loopCount = 0
    while temp != 0 {
        count += 1
        temp = temp & (temp-1)
        loopCount += 1
    }
    print("loop2 count: \(loopCount)")
    return count
}

例3:判断一个UInt数是否为2的整数幂次方

思路:能成为 2 的整数次幂的数,其二进制一定是这种类型的:1000 0000,如果 1000 0000 和它的 -1 后的数 0111 1111 做"与"操作,结果就是 0

func isPowerOfTwo(num: UInt) -> Bool {
    return (num & (num-1)) == 0
}

例4:找丢失数

一堆成对出现的数:1,2,3,4,3,2,1,找出其中缺失的一个数

思路:给定一个初始值,和数组里面的所有数做"异或"操作,成对出现的数和0做完异或操作后,结果依然是0,最后缺失的那个数4和0做异或操作,结果依然是4

func findLostNum(nums: [UInt]) -> UInt {
    var lostNum: UInt = 0
    for num in nums {
        lostNum = lostNum ^ num
    }
    return lostNum
}

如果有两个数缺失呢?

思路:分两组来计算。先求他们的异或结果,然后找出可以区分缺失的两个数的最右边为1的位的flag(缺失的两个数最右侧为1的位数肯定是不一样的),遍历数组,根据num和flag的"与"运算是否为0,分为2组,分别做异或运算,这里就和上面的过程一致了。

func findTwoLostNums(nums: [UInt]) -> (UInt, UInt) {
    var num1: UInt = 0
    var num2: UInt = 0
    var temp: UInt = 0
    for num in nums {
        // 得到缺失的两个数的结果
        temp = temp ^ num
    }
    // 找到最后为1的位
    var flag: UInt = 1
    while (flag & temp) == 0 {
        flag = flag << 1
    }
    // 找两个丢失的数字
    for num in nums {
        if (flag & num) == 0 {
            num1 = num1 ^ num
        } else {
            num2 = num2 ^ num
        }
    }
    return (num1, num2)
}

来自 https://leejnull.github.io/2019/09/07/2019-09-07/

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 8月5日 星期一 雨天 今天下午,我吃了八份披萨,本来有10份的,但我给外公留了两份,因为妈妈...
    醒梦N阅读 209评论 0 0
  • 生活不只眼前的苟且,还有诗和远方的田野。耳机里流淌出许巍那特别的嗓音时,我忽然特别想要去旅行。想要把今天工作里的不...
    听雨廿一阅读 257评论 0 0
  • 终于三天的中考结束了,快到要分开的时候了。班里的同学搞了次聚会,本来男孩不想去的,因为真的再也不想再看到女孩伤害他...
    GEDD520阅读 139评论 0 0
  • 2019.3.6Modeling local geometric structure of 3D point cl...
    nowherespyfly阅读 360评论 0 0
  • 我喉咙里很疼 水也掩埋不了的烧灼 是刚擦拭一新的屋子 又落了灰尘 我想硬挺着不吃药 用所有曾经健康的样子填满回忆 ...
    灌木丛阅读 161评论 0 1

友情链接更多精彩内容