剑指39 数组中出现次数超过半数的数
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。
你可以假设数组是非空的,并且给定的数组总是存在多数元素。
示例 1:
输入: [1, 2, 3, 2, 2, 2, 5, 4, 2]
输出: 2
这题本质是求数组中第k小的数。因为如果一个数出现次数超过一半,那么排序后数组的中位数肯定是它。如果使用排序,那么需要nlogn的时间。
直接采用二分法去查找第k小的数。每一次选取一个数(可以直接用最后一个或者第一个数)作为标志,把比它小的放到前面,比它大的放到后面,即partition的作用。该数最后的位置就是他在排好序的数组中的位置。如果这刚好是中位数,那么我们就找到了这个超过半数的数。
要熟练partition的写法和应用。
1 class Solution { 2 public: 3 int majorityElement(vector<int>& nums) { 4 int len=nums.size(); 5 return find_half(nums,len); 6 } 7 8 int partition(vector<int>& nums, int start, int end){ 9 if(end==start) 10 return start; 11 int smaller=start-1; 12 for(int index=start;index<end;index++){ 13 if(nums[index]<nums[end]){ 14 smaller++; 15 if(index!=smaller) 16 swap(nums[index],nums[smaller]); 17 } 18 } 19 ++smaller; 20 swap(nums[end],nums[smaller]); 21 return smaller; 22 } 23 24 int find_half(vector<int>& nums, int len){ 25 int start=0,end=len-1; 26 int pos=-1; 27 pos=partition(nums,start,end); 28 while(pos!=len/2){ 29 if(pos>len/2) 30 end=pos-1; 31 else 32 start=pos+1; 33 pos=partition(nums,start,end); 34 } 35 return nums[pos]; 36 } 37 };