題目描述
數組中有一個數字出現的次數超過數組長度的一半,請找出這個數字。例如輸入一個長度為9的數組{1,2,3,2,2,2,5,4,2}。由於數字2在數組中出現了5次,超過數組長度的一半,因此輸出2。如果不存在則輸出0。
方法一 ---- 基於隨機快排
如果數組中存在一個數字的出現次數大於數組長度一半,那么將這個數組排序后位於該數組的中位數就是這個數字。
在隨機快速排序中,現在數組中隨機選擇一個數字,然后調整數組中的數字的順序,使得比選中的數字小的的數字都在它的左邊,比他大的數字都在其右邊。如果這個選中的數字的下標剛好是n/2,那么這個數字就是數組的中位數;如果這個下標大於n/2,那么中位數應該在它的左邊,我們可以接着在它左邊部分的數組中查找;如果這個下標小於n/2,那么表示中位數在它的右邊,在右邊的數組中查找。是一個典型的遞歸過程。
/** * 利用Partition函數的時間復雜度為O(n)的算法 * @param array * @return */
public int MoreThanHalfNum_Solution(int [] array) {
if(array == null || array.length == 0) {
return 0;
}
if(array.length == 1) {
return array[0];
}
int middle = array.length / 2;
int start = 0;
int end = array.length - 1;
int index = Partition(array, start, end);
while(index != middle) {
if(index > middle) {
end = index - 1;
index = Partition(array, start, end);
}
else {
start = index + 1;
index = Partition(array, start, end);
}
}
int result = array[middle];
if(!CheckMoreThanHalf(array, result)) {
result = 0;
}
return result;
}
public boolean CheckMoreThanHalf(int[] elem, int result) {
int times = 0;
boolean isMoreThanHalf = true;
for (int i = 0; i < elem.length; i++) {
if(elem[i] == result) {
++times;
}
}
if(times * 2 <= elem.length) {
isMoreThanHalf = false;
}
return isMoreThanHalf;
}
public int Partition(int[] elem, int low, int high) {
int pivotkey = elem[low];
while(low < high) {
while((low < high) && elem[high] > pivotkey) {
high--;
}
swap(elem, low, high);
while((low < high) && elem[low] <= pivotkey) {
low ++;
}
swap(elem, low, high);
}
return low;
}
public void swap(int[] elem, int i, int j) {
int temp = elem[i];
elem[i] = elem[j];
elem[j] = temp;
}
方法二 ---- 根據數組特點
如果有一個數字在數組中出現次數大於數組的一半,那么也就是說他出現的次數比其他數字出現次數和還要多。我們可以設置兩個變量,一個保存數組中的一個數字,另外一個保存次數,遍歷數組,當遍歷到下一個數字時,如果下一個數字和之前保存的數字相同,次數加1;如果不同次數減1;如果次數為0,那么我們需要保存下一個數字,並將次數還原為1。
/** * 根據數組特點找出時間復雜度為O(n)的算法 * @param args */
public int MoreThanHalfNum_Solution_2(int [] array) {
if(array == null || array.length == 0) {
return 0;
}
if(array.length == 1) {
return array[0];
}
int tempNumber = array[0];
int times = 1;
for (int i = 1; i < array.length; i++) {
if(tempNumber == array[i]) {
times++;
}
else {
times--;
if(times == 0) {
tempNumber = array[i];
times = 1;
}
}
}
if(!CheckMoreThanHalf(array, tempNumber)) {
tempNumber = 0;
}
return tempNumber;
}