1. 程式人生 > >找出重複次數最多的數字

找出重複次數最多的數字

問題

給定一個大小為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;
}