先說一下題目吧,很簡單,就是給一組數組,求數組中的衆數,但是要用分治法。
看到這個題目還是比較迷的,求一個衆數,用什麼分治啊。最後參考了一下往上的各種答案,發現可以用快排的分割算法,思路如下:
首先是要運用快排的分割算法,設函數名爲quick,重複次數設置爲n,衆數設爲mode,數組長度即爲length.
- 選取中間的值作爲基準值來進行快排分割,這樣做可以儘量去避免重複的計算。
- 記k爲快排分割的返回值,即爲基準值的最終位置,同時在進行快排分割函數的時候需要記錄基準值的重複次數,如果大於n,那麼將mode更新爲基準值,同時更新n.
- 如果k-left>=n,那麼左邊的數可能存在衆數,對數組(left,k-1)進行快排分割
- 如果right-k>=n,那麼右邊的數可能存在衆數,對數組(k+1,right)進行快排分割
- 遞歸的去重複上述步驟。
C++實現的代碼如下:
#include<iostream>
using namespace std;
//全局變量存儲重數
int n = 0;
//全局變量存儲衆數
int mode = INT_MIN;
void Swap(int* arr, int num1, int num2)
{
int temp = arr[num1];
arr[num1] = arr[num2];
arr[num2] = temp;
}
//快排分割函數
int quick(int* arr, int low, int high)
{
int nTemp = 1;
//從中間選取基準
int mid = (low + high) / 2;
if (arr[low] > arr[mid])
Swap(arr, low, mid);
if (arr[low] > arr[high])
Swap(arr, low, high);
if (arr[mid] > arr[high])
Swap(arr, mid, high);
Swap(arr, low, mid);
int temp = arr[low];
while (low < high)
{
while (low < high )
{
if (temp == arr[high])
++nTemp;
if (temp > arr[high])
break;
--high;
}
if (low < high)
{
arr[low] = arr[high];
++low;
}
while (low < high )
{
if (temp == arr[low])
++nTemp;
if (temp < arr[low])
break;
++low;
}
if (low < high)
{
arr[high] = arr[low];
--high;
}
}
arr[high] = temp;
if (nTemp > n)
{
n = nTemp;
mode = temp;
}
return low;
}
void getMode(int* arr, int start, int end)
{
if (start >= end)
return;
int k = quick(arr, start, end);
if ((k - start) >= n)
getMode(arr, start, k - 1);
if ((end - k) >= n)
getMode(arr, k + 1, end);
}
int main()
{
int arr[] = { 3,4,1,2,2,2,3,3,5 };
getMode(arr, 0, sizeof(arr) / sizeof(arr[0]) - 1);
cout << "衆數爲:" << mode << " 重數爲:" << n << endl;
}
程序運行結果如下: