1.两个数字交换
- 不借助临时变量,交换两个变量的值
var a = 10
var b = 8
a = a ^ b
b = a ^ b
a = a ^ b
print(a)
print(b)
打印结果如下:
8
10
2.求无符号整数二进制中1的个数
2.1 给定一个无符号整数变量,求其二进制中表示“1”的个数,要求算法的执行效率尽可能高
- 思路:看一个8位整数 10 100 001 ,先判断最后一位是否为1,而“与”操作可以达到目的。可以把这个八位的数字与 00000001 进行“与“操作,如果结果为1,则表示当前八位数的最后1位为1,否则为0。怎么判断第二位呢?向右移位,在延续前面的判断即可。
func countOfOnes(num:UInt) -> UInt {
var count:UInt = 0
var temp = num
while temp != 0 {
count += temp & 1
temp = temp >> 1
}
print(count)
return count
}
countOfOnes(num: 1)
countOfOnes(num: 3)
countOfOnes(num: 8)
打印结果如下:
1
2
1
2.2 如果整数的二进制中有较多的0,那么我们每次右移一位做判断会很浪费,怎么改进前面的算法呢?又没有办法让算法的复杂度只和1的个数有关?
- 思路:为了简化这个问题,我们考虑只有高位有1的情况,如:11 000 000,如何跳过前面低位的6个0,而直接判断第七位的1?我们可以设计11 000 000 和10 111 111(也就是11 000 000 - 1)做“与”操作,消去最低位的1。如果得到的结果为0,说明我们已经找到或者消去里面最后一个1.如果不为0,那么说明我们消去了最低位的1,但是二进制中还有其他的1,我们的计数器要加1,然后继续上面的操作。
计数器 count = 0
步骤一:整数不为0,说明二进制里肯定有1,count = 1
11 000 000 & 10 111 111 = 10 000 000 ()消去第七位的1
步骤二:结果不为0,说明二进制中还有1,count = 2
10 000 000 & 01 111 111 = 0 (消去第八位的1)
步骤三:结果为0,终止,返回count = 2
func countOfOnes(num:UInt) -> UInt {
var count:UInt = 0
var temp = num
while temp != 0 {
count += 1
temp = temp & (temp - 1)
}
print(count)
return count
}
countOfOnes(num: 1)
countOfOnes(num: 3)
countOfOnes(num: 8)
打印结果如下:
1
2
1
3.引申:如何判断一个整数为2的整数次幂
给定一个无符号整型(UInt)变量,判断是否为2的整数次幂
- 思路:一个整数如果是2的整数次方,那么它的二进制表示中有且只有一位是1,而其他所有位都是0。
func isPowerOfTwo(num:UInt) -> Bool {
return (num & (num - 1)) == 0
}
isPowerOfTwo(num: 1)
isPowerOfTwo(num: 3)
isPowerOfTwo(num: 8)
结果如下:
true
false
true
网友评论