LeetCode/169. Majority Element.md
2018-09-03 22:00:48 +08:00

62 lines
2.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# [169. Majority Element](https://leetcode.com/problems/majority-element/description/)
# 思路
题目要求就是求数组主元素,主元素就是在数组中出现次数超过元素个数一半的元素,题目保证主元素一定存在。
## 思路一
若对数组nums进行排序则nums[n/2]就是主元素即题目转换成求数组中第n/2小的元素。
求数组第k小的元素最优的思想应该就是采用类似快排划分的思想
从数组中随机选择(一般选择第一个)一个元素作为pivot任何进行和快排划分一样的操作后数组被pivot划分为两部分nums[0...m-1]和nums[m+1...n-1], nums[m]=pivot。
讨论m和k的关系
(1) 若m=k, 即找到了直接返回pivot
(2) 若m<k, 对nums[m+1...n-1]递归地查找第k-m小的元素(对整个原数组来说还是第k小的元素)
(3) 若m>k, 对nums[0...m-1]递归地查找第k小的元素
该算法平均情况下时间复杂度为O(n), 空间复杂度取决于划分的方法。
## 思路二
本题其实是思路一能求解的题目的一个特例。下面介绍更快的方法:
# C++
## 思路一
```
// 提交结果为900ms相对于思路二可以说是很慢了
class Solution {
public:
// 定义递归函数
int kth_elem(vector<int>& nums, int low, int high, int k){
int pivot=nums[low];
int low_bk=low, high_bk = high; // 后面要修改low和high所以先备份
while(low < high){
while(low < high && nums[high] >= pivot) high--;
nums[low] = nums[high];
while(low < high && nums[low] <= pivot) low++;
nums[high] = nums[low];
} // low==high 退出循环
nums[low]=pivot;
// 以上为快排划分思想
if(low == k) return pivot;
else if(low > k) return kth_elem(nums, low_bk, low-1, k);
else return kth_elem(nums, low+1, high_bk, k);
}
int majorityElement(vector<int>& nums) {
int k = nums.size() / 2;
return kth_elem(nums, 0, nums.size() - 1, k);
}
};
```
## 思路二
```
// 提交结果为12ms较思路一有大幅提升
class Solution {
public:
int majorityElement(vector<int>& nums) {
int major = nums[0], count = 0;
for(int num : nums){ // 范围for语句
if(major == num) count++;
else if(count == 1) major = num;
else count--;
}
return major;
}
};
```