Swift - 位运算符

2022-03-16  本文已影响0人  村雨灬龑

位运算符

取反运算

与运算

或运算

异或运算

位左移和右移运算

无符号整数的位移操作

有符号整数的位移操作

补码表示的优点

位运算符经典算法

1.题目:不借助临时变量,交换两个变量的值.
    var a = 10 // 0000 1010
    var b = 8  // 0000 0100
    a = a ^ b  // a = 0000 1010 ^ 0000 0100 = 0000 1110
    b = a ^ b  // b = 0000 1110 ^ 0000 0100 = 0000 1010
    a = a ^ b  // a = 0000 1110 ^ 0000 1010 = 0000 0100
    print(a) // 打印: 8
    print(b) // 打印: 10
2.题目:给定一个无符号证书(UInt)变量,求其二进制表示中"1"的个数,要求算法的执行效率尽可能高

思路1
看一个8位整数1010 0001,先判断最后一位是否为1,而&操作可以达到目的.可以把这个8位的数与0000 0001进行&操作.如果结果为1,则表示当前8位数的最后一位是1,否则是0. 怎么判断第二位呢?向右移位(>>),再延续前面的判断即可.

func getCount(num: UInt) -> UInt {
    // 记录"1"的个数
    var count: UInt = 0
    // 转成变量
    var temp = num
    while temp != 0 {
        count += temp & 1
        temp = temp >> 1
    }
    return count
}
print(getCount(num: 0x10010101)) // 打印: 4

思路2
为了简化这个问题,我们只考虑高位有1的情况.例:1100 000,如何跳过低位的6个0,而直接判断第七位的1呢?我们可以设计1100 0000 和1011 0000 (也就是1100 0000 - 1)做&操作,消去低位的1.如果得到的结果为0,说明我们已经找到或者消去里面最后一个1.如果不为0,那么说明我们消去了最低位的1,但二进制中还有其他的1,我们的计数器需要加1,然后继续上面的操作.

操作步骤
计数器 count = 0
步骤一: 整数不为0,说明二进制里面肯定有1,count = 1
1100 0000 & 10011 1111(10011 1111 = 1100 0000 - 1) = 1000 0000 消去第七位的1
步骤二: 结果不为0,说明二进制里还有1,count = 2
1000 0000 & 0111 1111(0111 1111 = 1000 0000 - 1) = 0 消去第八位的1
步骤三: 结果为0,终止,返回count = 2

func getCount2(num: UInt) -> Int {
    var temp = num
    var count = 0
    
    while temp != 0 {
        count += 1
        temp = temp & (temp - 1)
    }
    return count
}
print(getCount2(num: 0x11010101)) // 打印:5
3.题目: 给定一个无符号整型变量,判断是否为2的整数次幂

思路:一个整数如果是2的整数次方,那么他的二进制表示中有且只有一位是1,其他都是0.根据前面分析,把这个整数减1后再和他自己做&运算,这个整数中唯一的1也就变成了0,也就得到的结果为0.

func isPowerOfTwo(num: UInt) -> Bool {
    return (num & (num - 1)) == 0
}
print(isPowerOfTwo(num: 0x00000011)) // 打印:false
print(isPowerOfTwo(num: 128)) // 打印:true
4.题目: 有很多成对出现的正整数保存在磁盘中,成对的数字不一定是相邻的,如2,3,4,5,4,2,3......,由于意外消失了一个数字,如何尽快找到是哪个数字消失?

思路:N表示任意数,N ^ 0的结果都是N他本身,N ^ N的时候结果是0.把所有的数字做异或运算,其中两两个相同的数字就会低消,剩余的就是那唯一不成对的一个数了

func findNum(nums: Array<Int>) -> Int {
    var result = 0
    for num in nums {
        result = result ^ num
    }
    return result
}
print(findNum(nums: [2,3,2,4,5,4,3])) // 打印:5
5.题目: 在题目4的基础上,如果丢失的是两个数字,并且这两个数字不相同,求找到这两个数字
func findTwoNum(nums: Array<UInt>) -> (UInt, UInt) {
    var lostNum1: UInt = 0
    var lostNum2: UInt = 0
    var temp: UInt = 0
    // 计算两个数的^结果
    for num in nums {
        temp = temp ^ num
    }

    var flag: UInt = 1
    while (temp & flag) == 0 {
        flag = flag << 1
    }
    
    for num in nums {
        if num & flag == 0 {
            lostNum1 = lostNum1 ^ num
        }else {
            lostNum2 = lostNum2 ^ num
        }
    }
    return (lostNum1, lostNum2)
}
print(findTwoNum(nums: [2,3,2,4,5,4,3,10])) // 打印:(10, 5)
上一篇下一篇

猜你喜欢

热点阅读