劍指Offer39:陣列中出現次數超過一半的數字
阿新 • • 發佈:2018-11-13
題目:
陣列中有一個數字出現的次數超過陣列長度的一半,請找出這個數字。
例如,輸入一個長度為9的陣列{1,2,3,2,2,2,5,4,2}.由於數字2在這個陣列中出現了5次,超過陣列 長度的一半,因此輸出2
分析:
若一個數組中有一個數字出現了陣列長度的一半以上,則必是這個陣列的中位數
方法一:最簡單粗暴,將陣列排序,找出中位數, 時間複雜度為O(nlog(n))
public int Method1(int[] nums) {
Arrays.sort(nums);
return nums[nums.length/2];
}
方法二:
基於Partition函式
* 隨機選擇一個數,比它小的都在這個數的左邊,比它大的都在這個數的右邊。
* 若這個數在排完之後的次序正好為n/2,那就是這個數,若不是。則在n/2的左邊或者右邊查詢
public int Method2(int[] nums) { int index = Partition(nums, 0, nums.length - 1); int start = 0; int end = nums.length - 1; while(index != nums.length /2) { if(index < nums.length /2) { start = index + 1; index = Partition(nums, start, end); }else { end = index - 1; index = Partition(nums, start, end); } } return nums[index]; } private int Partition(int[] nums, int start, int end) { if(start<0 || end >= nums.length) { return -1; } int small = start - 1; //作用是用來記錄比末尾值還要小的值應該在的位置 for(int i = start; i <= end; i++) { if(nums[i] < nums[end]) { small++; if(small != i) { int temp = nums[small]; nums[small] = nums[i]; nums[i] = temp; } } } /* * 把末尾值放在他應該在的地方去 */ small++; int temp = nums[end]; nums[end] = nums[small]; nums[small] = temp; return small; }
方法三:
採取一種類似投票的思路:由於存在一個數超過一半次數
因此,從0位次開始,第一個數字出現,記錄該數字,並記錄該數字出現的次數。
若下一個數字和上一個數字不一樣,times–。且上一個數字的出現次數為0次了。則換數字
public int Method3(int[] nums) { int times = 1; int result = nums[0]; for(int i = 1; i < nums.length; i++) { if(times == 0) { result = nums[i]; times = 1; }else { if(nums[i] != result) { times--; }else { times++; } } } return result; }