描述:乙個整型陣列裡除了1個數字之外,其他的數字都出現了兩次,請寫程式找出這個只出現一次的數字。
思路:利用異或的特性,x^y^x=x^x^y=y。對陣列所有元素進行一次異或操作,最後得到的就是只出現一次的數字。
描述:乙個整型陣列裡除了2個數字之外,其他的數字都出現了兩次,請寫程式找出這兩個只出現
1次的數字。
思路:1. 兩個數字肯定是不同的,則必有某一位上,兩個數字是不同的;
2. 可以對陣列所有元素進行一次異或操作,得到兩個數字哪一位是不同的;
3. 然後根據這一位將整個陣列分為兩個陣列,則兩個數會分在不同的陣列,並且相同的數一定會分在同乙個陣列;
4. 之後利用異或的方式得到數字。
描述:乙個整型陣列裡除了1個數字之外,其他的數字都出現了三次,請寫程式找出這個只出現一次的數字。
思路:最基本的工具還是利用異或的特性,但在使用方法上要做一些改變。
用兩個數字s1,s0記錄每一位
1的個數(
s1為高位數,
s0位低位數),如果等於3(即
011)則置零。設
s1_k
為高位數的第k位、
s0_k
為低位數的第k位,
a_k為其中乙個數的第k位:
則滿足:
輸入輸出
s1_k
s2_k
a_ks1_k
s2_k00
0000
0101
0100
1011
1010
0101
0111
等於3(
011),清零11
000不可能出現輸入為s1s0=11
的情況,因為一出現就已經置零,此時
s1s0
的值為任意值,不影響結果;為方便起見,記
s1s0=00
,便於理解。11
100得到:
s1 = (~s1 & ~s0 & a) | (~s1 & s0 & ~a);
s0= (~s1 & s0 & s0) | (s1 & ~s0 & ~a);
利用上述公式,對陣列所有元素進行操作,最後得到的s0就是只出現一次的數字。
描述:給出乙個整型陣列,每個元素都出現 k (
k>1
)次,只有乙個元素出現
p 次(
p >= 1
,p % k != 0
)。找到這個單獨的元素。
思路:大體而言,還是利用異或的特性,還有計數器的思想。
無論是異或,還是計數器的思想,在大學課程中學過數電的人肯定不會陌生。事實上,如果我們使用位操作來解決問題,那麼我們的思考方式就是之前我們學過的知識,畢竟,計算機的底層就是用「位」的概念來實現的。
關於此問題的詳細推導過程可以參考演算法題總結之找到陣列中出現次數唯一不同的數字
一文。(
)在此,只是簡單地描述一下使用計數器的思路,便於理解。
首先,針對每一位,用乙個計數器來統計1出現的次數,次數達到
k則置零,這樣每個出現
k次的元素,經過計數後最終的結果一定是
0。(若某一位上是
0,不影響結果)
然後,需要構建乙個k位的計數器,若有
m-1 < log k ≤ m,則至少需要
m個數來表示乙個
k位計數器,假設
m個數為
sm,sm-1,
……,s2,s1。(p
的大小無影響)
如果元素共有n位,
n-1位
n-2位
1位0位
sm-1
sm-2
……s1
s0代表1
個數代表1
個計數器
1. 每一行(藍色)代表1
個數。2. 每一列(黃色),代表1
個計數器;
m個數的第
0位聯合起來就是第
0位上的計數器。
3. 通過m
個數,得到了n個
k位計數器。
當計數器位數較少時,我們還可以採用上一節(2.高階版
)的方法,手動計算出所需的公式,但計數器位數較多時,這種方法就不合適了。
在此,我們借鑑最樸素的計數思想,對於乙個二進位制數,只有當第0位到第
i-1位均為
1,且新增到第
0位的數也為
1時,第
i位的數才會發生變化。設新來的數字
a,則上述過程用數學公式可以描述為:
si = si ^ ( si-1 & si-2 & ……
& s1 & s0 & a )
當計數器計數到k時,將其置零。即
sm-1,sm-2,
……,s2,s1,s0為k
的二進位制表述時,令每一位均置零。
令f = f ( sm-1,sm-2,……
,s2,s1,s0 )
,當且僅當sm-1,sm-2,……
,s2,s1,s0為k
的二進位制表述時,
f=0;
其餘情況,f=11……
111。
舉例說明:
k=3,則
f= ~( s1 & s0 )
;k=5,則
f= ~( s2 & ~s1 & s0 )
;則對於每一位,則有如下操作:si = si & f,這樣一來就將所有計數為
k的計數器歸零。
最後,則是利用所得計數器還原我們尋找的次數不同的那個數。
對於重複k次的數,在計數器中的結果一定是全零,對計數器的結果無影響,所以計數器的結果就只與重複
p次的那個數有關。
如果單獨元素的某一位為1,則相應位的計數器的值一定為p;
如果單獨元素的某一位為0,則相應位的計數器的值為0。
也就是說計數器的值只有兩種結果,0或p。
假設單獨元素的第i位、第
i+1位、第j位為
1,第i-1位、第
j-1位、第
j+1位為0,
p可以描述為0……
1011
,則可以有:
……i+1位
i位i-1位
……j+1位
j位j-1位
……sm-100
00…………s31
1001
0s200
0000
s1110
010s0
1100
10等於p等於0
計數器不為0
,則表示單獨元素相應位為
1;否則為
0。由此得到下面的結果11
0010
1. 可以發現,最終得到的結果(紫色)和p
的二進位制表述的非零位上對應的數字(
藍色)一致;
2. 也就是說,我們可以直接用p
的二進位制表述非零位對應的數字來作為最終結果。
最後,補充一種特殊情況:如果單獨元素為0,則計數器的結果均為
0;反之也成立。
刷題 數字在排序陣列中出現的次數
統計乙個數字在排序陣列中出現的次數。既然輸入的陣列是排序的,那麼我們很自然地可以想到用二分查詢演算法。我們可以先用二分查詢演算法找到乙個k,然後在找到的k的左右兩邊順序掃瞄。因為要查詢的數字在長度為n的陣列中有可能出現了n次,所以順序掃瞄的時間複雜度是o n 這樣和直接掃瞄整個陣列進行統計的效率是一...
數字在排序陣列中出現次數
統計乙個數字在排序陣列中出現的次數。思路 求乙個數字在這個排序陣列中出現的次數,首先想到的是使用二分查詢,當我找到乙個位置,然後往前就可以到達最前面第乙個出現該數字的位置,往後就可以到達最後面最後乙個出現該數字的位置,然後兩個位置相減此時就得到該數字出現的次數。但是問題在於我用二分查詢到位置後,然後...
演算法複習 數字在排序陣列中出現的次數
統計乙個數字在排序陣列中出現的次數 1 遍歷一次求出個數 2 使用二分查詢求出第乙個和最後乙個的下標。如何求第乙個數字呢,假如要找的數字和中間的數字相等,則判斷其前面乙個數字 下標不越界 假如不相等則是第乙個數字。同理可求最後乙個數字。需要注意的是陣列下標越界問題。public static int...