歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

【經典面試題】統計數組

原題

給定數組A,大小為n,數組元素為1到n的數字,不過有的數字出現了多次,有的數字沒有出現。請給出算法和程序,統計哪些數字沒有出現,哪些數字出現了多少次。能夠在O(n)的時間復雜度,O(1)的空間復雜度要求下完成麼?

分析

這個題目,是有一定技巧的。技巧是需要慢慢積累,待經驗多了之後,可以靈感或者直覺,就產生了技巧。如果不知道技巧,那該怎麼辦呢?

在開始分析之前,說明兩個問題: 

  • 原數組是沒有排序的。如果排序了,很簡單的。

  • O(1)的空間含義,可以使用變量,但不能開辟數組或者map等來計數。 

這個題目,很直接的解法就是兩層遍歷,O(n^2)的復雜度,O(1)的空間。空間滿足了,但是時間沒有。 

很多類似的題目,都會用XOR的方法,大家仔細想一下,這個題目,可以麼?或者這個題目和可以用XOR的題目的差異在哪兒?最直接的就是,每一個數字的重復的次數是不同的。 

還有就是以空間換時間的方法,例如用hash map或者數組來計數。時間滿足了,但是空間沒有滿足。 

那怎樣才能有時間復雜度O(n),空間復雜度O(1)的算法呢?不能開辟新的空間,那麼只剩下,重復利用數組A。那麼該如何利用數組A呢? 

首先,我們介紹一種三次遍歷數組的方法,我們都考慮數組從0開始: 

  • 第一次遍歷:對於每一個A[i] = A[i] * n

  • 第二次遍歷:對於每一個i,A[A[i]/n]++

  • 第三次遍歷:對於每一個i,A[i] % n就是出現次數 

A[i]應該出現在A中的A[i]位置,乘以n、再除以n,很容易的來回變換;第二次遍歷,對於A[i]本來所在的位置不斷增1,但絕對不對超出n的,那每一個i出現的次數,就是A[i]對n取余。 

還有一種兩次遍歷的方法,也是上面的思路:題目中數組是1到n,為了方便算法考慮,以及數組存儲方便,我們考慮0-n-1,結果是相同的。 考慮A[i],現在位置是i,如果采用A來計數,它的位置應該是A[i] % n,找到計數位置,該如何處理這個位置呢?加1麼? 顯然不可以,這裡有一個技巧,就是加n,有兩個原因 

  • 加n可以保證A[i] % n是不變的

  • A數組,最後每一個元素表示為A[i] = x + k*n,其中x<n,並且k就是我們要統計的頻率。 

這樣,大家也能夠明白,為什麼A[i]在A中的位置,表示為A[i] % n了吧。上面第二種思路,轉換為代碼如下:

【分析完畢】

Copyright © Linux教程網 All Rights Reserved