題目描述
數組中有一個數字出現的次數超過數組長度的一半,請找出這個數字。例如輸入一個長度爲9的數組{1,2,3,2,2,2,5,4,2}。由於數字2在數組中出現了5次,超過數組長度的一半,因此輸出2。如果不存在則輸出0。
解析:
一種很常規的思路是排序,排過序後,從首元素開始遍歷數組,用一個整型變量times記錄次數,一個整型變量記temp錄正在判斷的數字,如果遍歷到的數字和正在判斷的數字相同,times加1,否則,times就達到了前者出現的最大次數,判斷它是否符合條件,如果符合,返回這個元素,如果不符合,就將times置1,temp置爲當前遍歷到的數字,直到遍歷結束,但要注意數組長度爲1和爲0的特殊情況。當然這個方法不太好,因爲時間複雜度爲O(nlogn),而本題是存在時間複雜度爲O(n)的解法的。
import java.util.Arrays;
public class Solution {
public int MoreThanHalfNum_Solution(int [] array) {
if(array.length == 0 || array == null){
return 0;
}
if(array.length == 1){
return array[0];
}
//調用Arrays類的靜態方法sort()來排序
Arrays.sort(array);
int start=0;
int end=0;
for(int i=1;i<array.length;i++){
if(array[i]== array[start]){
continue;
}else{
if(2*(i-start)>array.length){
return array[start];
}
start = i;
}
}
return 0;
}
}
另一種思路是這樣的,如果存在一個數字,出現的次數超過一半,那麼它和其他數字“做抵消”,以“一換一”的形式,那麼最後剩下的一定是這個數字(因爲它出現的次數比其餘數字加起來還多),所以可以定義兩個變量,一個變量times記錄次數(但不是總次數),一個記錄temp當前正在判斷的數字,遍歷數組,如果當前數字和正在判斷的數字相等,times加一,否則times減一,如果times爲0,則temp置爲當前遍歷到的數字,times置爲1,直到遍歷結束。
遍歷結束後,並不知道temp是不是所要尋找的數字,但這時只有兩種情況,一種是temp爲所要尋找的數字,一種是不存在索要尋找的數字,這時候可以再遍歷一遍數組,判斷temp是否符合條件。
第一次用這種方法時,我試圖在第一次遍歷時設置一個變量maxTimes,記錄正在判斷的數字出現的最大次數,這樣就不用第二次遍歷了,但是發現失敗了,因爲數組無序,相同數字不挨着,maxTimes常常會被置0,無法達到目的。所以,第二次遍歷應該還是必要的。
public class Solution {
public int MoreThanHalfNum_Solution(int [] array) {
if(array.length == 0 || array == null){
return 0;
}
if(array.length == 1){
return array[0];
}
int times = 1;
int temp = array[0];
for(int i=1;i<array.length;i++){
if(temp == array[i]){
times++;
}
if(temp != array[i]){
times--;
if(times == 0){
temp = array[i];
times =1;
}
}
}
if(check(array,temp)){
return temp;
}else{
return 0;
}
}
public boolean check(int[] array,int temp){
int times=0;
for(int i=0;i<array.length;i++){
if(array[i] == temp){
times++;
}
}
if(times*2>array.length){
return true;
}else{
return false;
}
}
}