找數字續;及缺失的數字分析

紫鳳發表於2013-09-17

今日面試題:找數字續

一個陣列A,數字出現的情況,只有以下三種:

1. 一些數字只出現一次

2. 一些數字出現兩次

3. 只有一個數字出現三次

請給出方法,找到出現三次的數字h

缺失的數字分析

原題

給定一個無序的整數陣列,怎麼找到第一個大於0,並且不在此陣列的整數。比如[1,2,0] 返回 3, [3,4,-1,1] 返回 2。最好能O(1)空間和O(n)時間。

分析

首先陣列是無序的,找到第一個大於0且不在陣列中的元素,就是要找到大於0且不在陣列中的最小的整數。要怎麼處理呢?要找到最小的,不妨嘗試從小到 大排序,然後從1開始,查詢是否在陣列中,可以利用二分查詢。這樣整體的時間複雜度是O(nlogn),空間複雜度是O(1)。

離題目的要求,還差一些。如何改進呢?針對排序好的陣列,我們做如下的觀察:

  • 當缺失的數字為1的時候,A[0]<=0, A[1] != 1

  • 當缺失的數字為2的時候,A[0]<=0, A[1] = 1, A[2] != 2

  • 當缺失的數字為3的時候,A[0]<=0, A[1] = 1, A[2] = 2, A[3] != 3

通過上面的觀察,可以發現,其實並不需要整個陣列是有序的,只需要讓陣列中的0

1. 如果A[i]=n,則continue;

2. 如果A[i]=A[A[i]],則continue;

3. 如果0<A[i]<n,那麼可以還原,則swap(A[i], A[A[i]]),然後跳轉到步驟2

然後,陣列中如果存在0

  • 從1開始遍歷,如果A[i]!=i,則i就是要找的數

  • 如果遍歷完,沒有找到,則說明i從[1,n-1],都有A[i]=i,那麼這個時候就看A[0],如果A[0]是n,則返回n+1,如果A[0]不是n,則返回n,即可。

上面演算法的時間複雜度是O(n)麼?有的同學會想,在swap之後,仍然到第2步,可能還會出現交換,所以時間複雜度要高於O(n)。但實際上,swap之後,是會發生再次的交換,但我們可以保證,每一次交換,都會使得一個數字還原,即A[i]=i,再一次交換,會讓一個新的數字還原。 假設陣列中,可以還原的數字個數為k,則需要交換k次,k最多為n-1。這裡要很小心,因為總的交換次數是k,並不是對於每一個元素,都會產生k次交換。 如果是後者,總的時間複雜度就是O(kn)了,但因為總的交換次數是k,所以總的時間複雜度是O(n+k),就是O(n)。

【分析完畢】

本文來自微信:待字閨中,2013-09-11釋出,原創@陳利人 ,歡迎大家繼續關注微信公眾賬號“待字閨中”。

相關文章