乙個整型陣列 nums 裡除兩個數字之外,其他數字都出現了兩次。請寫程式找出這兩個只出現一次的數字。要求時間複雜度是o(n),空間複雜度是o(1)。在做這道題之前你需要知道 異或運算子的性質。也就是
^
;
異或:相同為0,不同為1
舉個例子:3 ^ 5
3的二進位制:0 0 1 1
5的二進位制:0 1 0 1
異或結果: 0 1 1 0
異或滿**換律,結合律,自反性
由此結合題目我們可以從數字的異或入手。
因為只有兩個數字只出現過一次,其餘的數都出現了兩次,所以對這個陣列中的所有數字進行異或操作的結果也就是對只出現一次的兩個數進行異或。我們把這倆數字異或的結果設為res
.
現在關鍵是怎樣把他們分開?
因為兩個數字如果相同,那麼他們的二進位制的每一位都相同,如果兩個數不同,那麼他們的二進位制中肯定有不同的那一位。
由於異或的性質是,同一位相同則為 0,不同則為 1. 我們將所有數字異或的結果一定不是 0,也就是說至少有一位是 1.
我們隨便取乙個,分組的依據就來了, 就是你取的那一位是 0 分成 1 組,那一位是 1 的分成一組。
方法一:
int h =1;
while
((h&res)==0
)//從res中找第乙個不是0的那一位(從右往左)
方法二:
int h = res&
(-res)
;//這個需要試一下,相反數的二級制計算時:先取反,再加一,在進行&就能找到res的二級制中第乙個 1
//例如 5 的二進位制是 0101 -5的二進位制是 1011 進行&得到 0001,所以從右往左,5的二進位制的第一位是 1.
我們將這兩個分開以後,只需要進一步判斷陣列中的元素和 h 做與 運算。
如果n(這裡指數組中的元素)& h == 0,代表當前元素的這一位上是0,
如果 (n & h )==n那麼就代表當前元素這一位上是1,這樣就把整個陣列分開了,同時兩個只出現一次的數字也分開了。
分成兩組後,最後進行異或運算,剩餘的結果就分別是只出現1次的那兩個數。(因為 x ^ x = 0, x ^ 0 = x)
public
int[
]singlenumbers
(int
nums)
int h=res&
(-res)
;//從右往左找到第乙個是1的位
int a=
0,b=0;
//用來儲存分組後的結果
for(
int n:nums)
else
}return
newint
;}
以上有理解不到位的地方歡迎各位指出!
劍指Offer 56 陣列中重複的數字
題目描述 在乙個長度為n的陣列裡的所有數字都在0到n 1的範圍內。陣列中某些數字是重複的,但不知道有幾個數字是重複的。也不知道每個數字重複幾次。請找出陣列中任意乙個重複的數字。例如,如果輸入長度為7的陣列,那麼對應的輸出是第乙個重複的數字2。演算法1 bool duplicate int numbe...
劍指Offer56 陣列中數字出現的次數
題目一 陣列中數字只出現一次的兩個數字。乙個整形陣列裡除兩個數字之外,其它數字都出現了兩次。請寫程式找出這兩個只出現一次的數字。要求時間複雜度為o n 空間複雜度是o 1 解題思路 位運算中異或運算的性質 兩個相同數字等於0,乙個數和零異或還是它本身。當只有乙個數出現一次時,我們把陣列中所有的數依次...
劍指offer 56題 陣列中數字出現的次數2
在乙個陣列 nums 中除乙個數字只出現一次之外,其他數字都出現了三次。請找出那個只出現一次的數字。示例 1 輸入 nums 3,4,3,3 輸出 4 示例 2 輸入 nums 9,1,7,9,7,9,7 輸出 1 利用位運算,當乙個陣列 現的其他數字都為3次時,所有數字的每一位加起來的各自的值對3...