題目來自 leetcode,這是個人 leetcode 解題集,目前在刷第一輪。但願能夠一塊兒研究題目。javascript
Given a sorted array consisting of only integers where every element appears twice except for one element which appears once. Find this single element that appears only once.
給出一個由整數
1 組成的有序
2 數組。數組中有一個元素只出現一次,其他的所有出現兩次。找出這個只出現一次的元素。java
Example 1:git
Input: [1,1,2,3,3,4,4,8,8] Output: 2
Example 2:github
Input: [3,3,7,7,10,11,11] Output: 10
Note: Your solution should run in O(log n) time and O(1) space.數組
func singleNonDuplicate(nums []int) int { len := len(nums) for i, v := range nums { if i == len - 1 { // 當前元素若是已是最後一個元素,直接 break. 同時也是爲了防止下面的 nums[i+1] 數組越界 break } nums[i+1] = v ^ nums[i+1] // 當前元素和下一個元素 xor 的結果會被保存到下一個元素 } return nums[len-1] }
func singleNonDuplicate(nums []int) int { left := 0 right := len(nums) - 1 mid := 0 for left <= right { mid = (left + right) / 2 if left == right { // left = right, 則 mid = left = right 。即當前值爲該查找過程的最後一個值 break } if mid % 2 == 1 { // mid % 2 == 1 說明 nums[mid] 左右各有奇數個元素 if nums[mid] == nums[mid+1] { right = mid - 1 } else if nums[mid] == nums[mid-1] { left = mid + 1 } else { break } } else { // mid % 2 == 0 說明 nums[mid] 左右各有偶數個元素 if nums[mid] == nums[mid+1] { left = mid + 2 } else if nums[mid] == nums[mid-1] { right = mid - 2 } else { break } } } return nums[mid] }
var singleNonDuplicate = function(nums) { return nums.reduce((x,y)=>x^y); };
時間複雜度 O(n)
。app
若是 go 有 reduce 功能的話會很好作,好比用 js 直接 return nums.reduce((x, y) => x ^ y)
搞定。這種解法主要是用到了 xor (異或) 位運算符的其中 3 個性質 :this
根據這三個性質 :spa
[1,1,2,3,3,4,4,8,8] 1 ^ 1 ^ 2 ^ 3 ^ 3 ^ 4 ^ 4 ^ 8 ^ 8 = 0 ^ 2 ^ 0 ^ 0 ^ 0 = 2 // 也就是說把整個數組元素進行異或,獲得的最後結果就是不重複值
因爲 go 沒有 reduce, 咱們在 range 的時候都把 當前元素 ^ 下一個元素
的結果覆蓋下一個元素的值,以此來達到 reduce 的效果。這樣在遍歷一遍以後 nums 的最後一個元素就是咱們想要的結果,時間複雜度是 O(n)。code
時間複雜度 O(log(n))
。 orm
題目要求時間複雜度是 O(log(n))
,再加上已經說明了數組是有序的。其實也只剩下 二分查找
這一種思路了。 二分查找中,每一次迭代都要判斷出目標元素在中間元素的左邊仍是右邊,每一次迭代捨棄掉一半不符合條件的數據,直到找到目標元素。
即,每次迭代要判斷出不重複值是在中間值的左邊仍是右邊。
/** * 由題目可知,nums 只能有奇數個數元素,因此必定會有處於中間的元素。有兩種狀況: * 1. 中間元素左右兩邊有奇數個元素,如: 1,1,2,2,3,4,4. 中間元素 2 左右兩側各有 3 個元素 * 2. 中間元素左右兩邊有偶數個元素,如: 1,1,2,2,3,3,4,5,5. 中間元素 3 左右兩側各有 4 個元素 */ if mid % 2 == 1 { // mid % 2 == 1 說明 nums[mid] 左右各有奇數個元素 // eg: 1,1,2,3,3,4,4 . // 若是中間元素 nums[3] 和 nums[4] 是一對重複值,則 nums[3] 左側的奇數個元素必定有一個元素沒法與其餘元素組成一對重複值 // 即,不重複值必定在 nums[mid] 左側,right = mid - 1 if nums[mid] == nums[mid+1] { right = mid - 1 } else if nums[mid] == nums[mid-1] { // 同理,不重複值必定在 nums[mid] 右側 left = mid + 1 } else { break } } else { // mid % 2 == 0 說明 nums[mid] 左右各有偶數個元素 // eg: 1,1,2,2,3,3,4,5,5 // 中間元素 nums[4] 和 nums[5] 是一對重複值,則 nums[5] 右側的 4,5,5 是奇數個元素,已定有個一元素沒法與其餘元素組成一對重複值 // 即,不重複值已定在 nums[mid] 右側,left = mid + 2 if nums[mid] == nums[mid+1] { left = mid + 2 } else if nums[mid] == nums[mid-1] { // 同理,不重複值必定在 nums[mid] 左側 right = mid - 2 } else { break } }
The Hamming distance between two integers is the number of positions at which the corresponding bits are different.
Given two integers x
and y
, calculate the Hamming distance.
求整數 x 和 y 的漢明距離。
Note:
0 ≤ x, y < 231.
example
Input: x = 1, y = 4 Output: 2 Explanation: 1 (0 0 0 1) 4 (0 1 0 0) ↑ ↑ The above arrows point to positions where the corresponding bits are different.
func hammingDistance(x int, y int) int { bits := strconv.FormatInt(int64(x^y), 2) var count1 int for _,n := range bits { if string(n) == "1" { count1 ++ } } return count1 }
題目要求計算兩個整數的 漢明距離。漢明距離的計算對象通常是兩個等長字符串。因此其實咱們要計算的是這兩個整數的二進制字符串的漢明距離。
簡單的作法就是利用異或符的性質:相同爲 0 ,不一樣爲 1
。 將 x ^ y
的計算結果轉爲二進制字符串,求出這個字符串中 "1"
出現的次數便可。