題目描述:使用二進制位來表示整數,好比將二進制位的第 9 位置爲 1 來表示整數 9 。數組
二進制:10 0000 0000
表明 十進制:9
bash
由於 Int 類型佔用四個字節,共 32 位,若是每一位存儲一個整數的話,則數組的第一個元素能夠表示: 1~32,第二個元素能夠表示:33~64 ...以此類推。函數
首先定義一下要使用的變量,假設咱們須要存儲 1億 之內的整數 :測試
let bits = 32 // Int 佔用 4 個字節,一共 32 位
let shift = 5 // 32 爲 2 的 5 次方,即偏移量爲 5
let mask = 31
let n = 10_000_000
var nums = Array(repeating: 0, count: 1 + n / bits)
複製代碼
接下來咱們看一下添加函數。該函數須要如下的三步:ui
下面來詳細說一下上面的三步:spa
以十進制整數 45 舉例。下面是計算 45 的索引代碼:code
let index = 45 >> shift // 等價於 45 / 32
複製代碼
上述代碼計算得出 45 的索引爲 1 ,即 index = 1。計算出索引以後要計算在該索引存儲的具體值。索引
以 45 來舉例:element
let power = 1 << (45 & mask) // 至關與求 2 的 45 次方
複製代碼
let oldValue = nums[index]
let newValue = oldValue | power
nums[index] = newValue
複製代碼
採用或的方式是由於這樣不會影響上次存儲的值,由於上次存儲的值已將相應位置爲 1 。rem
完整的添加函數:
func set(_ newElement: Int) {
let index = newElement >> shift
let power = 1 << (newElement & mask)
let oldValue = nums[index]
let newValue = oldValue | power
nums[index] = newValue
}
複製代碼
移除函數共須要三步:
let power = 1 << (element & mask)
let negation = ~power
let oldValue = nums[index]
let newValue = oldValue & negation
nums[index] = newValue
複製代碼
完整的移除函數:
func remove(_ element: Int) {
let index = element >> shift
let power = 1 << (element & mask)
let negation = ~power
let oldValue = nums[index]
let newValue = oldValue & negation
nums[index] = newValue
}
複製代碼
獲取函數共須要三步:
完整代碼:
func get(_ element: Int) -> Int {
let index = element >> shift
let value = 1 << (element & mask)
return nums[index] & value
}
複製代碼
set(30)
print(nums[0]) // 2 的 30 次方 1073741824
print(get(30)) // 1073741824
remove(30)
print(get(30)) // 0
複製代碼
易讀版完整代碼:
func set(_ newElement: Int) {
let index = newElement >> shift
let power = 1 << (newElement & mask)
let oldValue = nums[index]
let newValue = oldValue | power
nums[index] = newValue
}
func remove(_ element: Int) {
let index = element >> shift
let power = 1 << (element & mask)
let negation = ~power
let oldValue = nums[index]
let newValue = oldValue & negation
nums[index] = newValue
}
func get(_ element: Int) -> Int {
let index = element >> shift
let value = 1 << (element & mask)
return nums[index] & value
}
複製代碼
下面的代碼版本爲簡易版本(我的感受不太易讀):
func set(_ newElement: Int) {
let index = newElement >> shift
let curNum = nums[index]
nums[index] = curNum | (1 << (newElement & mask))
}
func remove(_ element: Int) {
let index = element >> shift
nums[index] &= ~(1 << (element & mask))
}
func get(_ element: Int) -> Int {
let index = element >> shift
return nums[index] & (1 << (element & mask))
}
複製代碼