方法一:
數組排序,然后中間值肯定是要查找的值。 排序最小的時間復雜度(快速排序)O(NlogN),加上遍歷。
方法二:
使用散列表的方式,也就是統計每個數組出現的次數,輸出出現次數大於數組長度的數字。
方法三:
出現的次數超過數組長度的一半,表明這個數字出現的次數比其他數出現的次數的總和還多。
考慮每次刪除兩個不同的數,那么在剩下的數中,出現的次數仍然超過總數的一般,不斷重復該過程,排除掉其他的數,最終找到那個出現次數超過一半的數字。這個方法的時間復雜度是O(N),空間復雜度是O(1)。
換個思路,這個可以通過計數實現,而不是真正物理刪除。在遍歷數組的過程中,保存兩個值,一個是數組中數字,一個是出現次數。當遍歷到下一個數字時,如果這個數字跟之前保存的數字相同,則次數加1,如果不同,則次數減1。如果次數為0,則保存下一個數字並把次數設置為1,由於我們要找的數字出現的次數比其他所有數字出現的次數之和還要多,那么要找的數字肯定是最后一次把次數設為1時對應的數字。
public int MoreHalf(int[] nums) {
int result = 0;
int count = 1;
if (nums.length == 0)
return -1;
result = nums[0];
for (int i = 1; i < nums.length; i++) {
if (count == 0) {
result = nums[i];
count = 1;
continue;
}
if (result == nums[i])
count++;
else
count--;
}
count = 0;
for (int i = 1; i < nums.length; i++) {
if(result = nums[i])count++;
}
if(count > nums.length/2)
return result ;
return 0;
}
方法四:
改進的快排,前面提到,如果對一個數組進行排序,位於中間位置的那個數字肯定是所求的值。對數組排序的時間復雜度是O(nlog(n)),但是對於這道題目,還有更好的算法,能夠在時間復雜度O(n)內求出。
借鑒快速排序算法,其中的Partition()方法是一個最重要的方法,該方法返回一個index,能夠保證index位置的數是已排序完成的,在index左邊的數都比index所在的數小,在index右邊的數都比index所在的數大。那么本題就可以利用這樣的思路來解。
- 通過Partition()返回index,如果indexmid,那么就表明找到了數組的中位數;如果index<mid,表明中位數在[index+1,end]之間;如果index>mid,表明中位數在[start,index-1]之間。知道最后求得indexmid循環結束。
public int Partition(int[] nums,int start,int end){
int pivotkey = nums[start];
int origin = start;
while(start<end){
while(start<end&&nums[end]>=pivotkey) end--;
while(start<end&&nums[start]<pivotkey) start++;
swap(nums,start,end);
}
swap(nums,start,end);
swap(nums,origin,end);
return end;
}
public int[] swap(int[] ints, int x, int y) {
int temp = ints[x];
ints[x] = ints[y];
ints[y] = temp;
return ints;
}
public int MoreThanHalf(int[] nums){
if(nums.length==0)
return -1;
int start = 0;
int end = nums.length-1;
int index = Partition(nums, start, end);
int mid = nums.length/2;
while(index!=mid){
if(index>mid)
//如果調整數組以后獲得的index大於middle,則繼續調整start到index-1區段的數組
index = Partition(nums, start, index-1);
else{
//否則調整index+1到end區段的數組
index = Partition(nums, index+1, end);
}
}
return nums[index];
}
