剑指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 };

 

posted @ 2020-07-04 21:05  __rookie  阅读(141)  评论(0编辑  收藏  举报