找出重複次數最多的數字
阿新 • • 發佈:2019-01-26
問題
給定一個大小為n的陣列,該陣列包含數字的範圍在 [0...k-1], k是一個正整數,k < = n。在這個陣列找到重複次數最多的數字。
例如, 假設k= 10給定的陣列是arr[] = {1, 2, 2, 2, 0, 2, 0, 2, 3, 8, 0, 9, 2, 3},最大的重複數量將是2。
期望的時間複雜度是O(n),空間複雜度為O(1),允許修改原陣列。
分析
方法一:使用雙重迴圈,逐個判斷每個元素出現的次數,複雜度為O(n^2). 改進的做法是,使用雜湊,用一個大小為k的陣列count[] ,用來記錄每個數字出現的次數,count[arr[i]]. 就代表 arr[i]重複的次數。這種方法遍歷一次即可,但是空間複雜度為 O(k).
注意題目中的另一個條件,可以修改原陣列,因此可以考慮用原陣列代替 count[] 陣列,為了能保證修改之後還要用到原來的資料,修改應該是可恢復的。資料範圍在 [0...k-1] 內也是一個很重要的條件。這裡需要用到一些簡單的數學知識即可。
方法二:遍歷arr[]中的元素,做如下操作 arr[arr[i]%k] += k . 之所以增加k是因為可以恢復修改過的arr[i],它最初的資料即為 arr[i] % k , 同時 arr[i] / k 就代表數字 i 出現的次數。此方法的前提是要保證計算不會溢位。但是當有多個數字重複次數一樣多時只能輸出其中的一個。不知各位有什麼好的方法可以將多個同時輸出來。
方法二程式碼:
#include<iostream> using namespace std; int FindMaxNumber(int *arr,int len, int k) { int i; int ans=arr[0]; int maxCnt=0;// maxCnt/k 為當前最大的重複次數 for(i=0;i<len;i++) { arr[arr[i]%k]+=k; if(maxCnt < arr[arr[i]%k]) { maxCnt = arr[arr[i]%k]; ans = arr[i]%k; } } //恢復陣列 for ( i = 0; i< len; i++) { arr[i] = arr[i] % k; } return ans; } int main() { int arr[5]={3,1,3,1,1}; int num=FindMaxNumber(arr,5,4); cout<<num<<endl; return 0; }