题目
给定一个大小为 n 的数组,找到其中的多数元素。多数元素是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素。
你可以假设数组是非空的,并且给定的数组总是存在多数元素。
示例1
输入: [3,2,3]
输出: 3
示例2
输入: [2,2,1,1,1,2,2]
输出: 2
思路一
- 使用一个map,遍历一遍数组,记录每个数字出现的次数。
- 再遍历一遍,找到第一个出现次数大于 ⌊ n/2 ⌋ 的元素。
代码一
class Solution {
public:
int majorityElement(vector<int>& nums) {
map<int,int> m;
int half = ( nums.size() - 1 ) >> 1;
int res = 0;
for ( auto& n : nums )
++m[n];
for ( auto&n : nums ) {
if ( m[n] > half ) {
res = n;
break;
}
}
return res;
}
};
思路二
- 大于 ⌊ n/2 ⌋ 的元素。如果一个数组有序,一个数出现次数大于⌊ n/2 ⌋,那么在 ⌊ n/2 ⌋处肯定是这个元素。
- 所以可以使用快排的思想,当得到一个数m,m左边的数都小于m, m右边的数都大于m。
- 如果m的位置等于⌊ n/2 ⌋,则返回。
- 如果m的位置小于⌊ n/2 ⌋,则在m的右边来一次快排,再找到一个新的m。
- 否则在m的左边进行一次快排,找到一个新的m。
- 重复上述知道找到⌊ n/2 ⌋的位置。
代码2
class Solution {
public:
// 不用额外空间
int majorityElement(vector<int>& nums) {
int half = nums.size() >> 1;
helper( nums, 0, nums.size() - 1, half );
return nums[half];
}
void helper( vector<int>& nums, int lo, int hi, const int& half ) {
int mid = partition( nums, lo, hi );
if ( mid == half )
return;
if ( mid > half )
helper( nums, lo, mid - 1, half );
else
helper( nums, mid + 1, hi, half );
}
int partition( vector<int>& nums, int lo, int hi ) {
int index = lo + rand() % ( hi - lo + 1 );
swap( nums[lo], nums[index] );
int pivot = nums[lo];
while ( lo < hi ) {
while ( lo < hi && pivot <= nums[hi] )
--hi;
nums[lo] = nums[hi];
while ( lo < hi && pivot >= nums[lo] )
++lo;
nums[hi] = nums[lo];
}
nums[lo] = pivot;
return lo;
}
void swap( int& a, int& b ) {
int temp = a;
a = b;
b = temp;
return;
}
};