所謂主元素, 就是指在數組中出現次數超過N/2的元素, 給出大小為N的數組, 判斷是否存在主元素, 若存在,求出主元素.
我的思路
BF解法就不講了, 我一開始想到的是如果這組數組中數字的范圍夠小, 或者數字的類型夠少, 完全可以用一個數組來記錄各個數字出現的次數, 然后再遍歷一次即可找出出現次數最多的, 最后判斷這個次數是否超過了N/2, 這樣算的話, 只需要O(N)的時間復雜度, 這也是典型的用空間換時間. 如果數字足夠多, 范圍足夠大, 那就只能快排了, 排完之后這個題目其實也就是轉化成了我說的上一種方式.
聰明人的解法(來源於網絡)
首先我們來分情況, 假設這個元素存在的話, 我們先假設數組中第一個元素是該元素, 然后計數變量初始化為1, 此時從第二個元素開始遍歷數組, 如果接下來這個元素是當前假定的主元素,那么計數變量+1, 否則計數變量-1, 當計數器數量即將要下降到0的時候, 將當前位置的元素設為主元素, 計數變量重新刷新為1. 那么一條很重要的屬性就是遍歷數組結束的時候的假定主元素就是該數組的首元素. 此時我們再假設這個元素可能不存在, 那么其實我們只需要確定我們剛才求出來的最后一個假定元素是不是主元素就可以了. 代碼實現非常簡單, 但其實要想到這個算法, 就不是這么容易了, 哎, 反正我是想不到...
int findMainElement(const int* array, size_t size) {
int candidate = array[0];
int counter = 1;
for (int i = 1; i < size; ++i) {
if (candidate == array[i]) {
++counter;
}
else if (counter == 1) {
candidate == array[i];
}
else {
--counter;
}
}
counter = 0;
for (int i = 0; i < size; ++i) {
if (candidate == array[i]) {
++counter;
}
}
if (counter * 2 > size) {
return candidate;
}
else {
return -1;
}
}