[Leetcode] 169. Majority Element 解题报告
2017-06-04 12:42
381 查看
题目:
Given an array of size n, find the majority element. The majority element is the element that appears more than
You may assume that the array is non-empty and the majority element always exist in the array.
思路:
虽然这道题目的官方难度是easy级别,但我感觉这道题目还是值得好好讨论一下,因为这里面可能会涉及到几个很不错的思想和算法。
1、暴力法:就是扫描数组,并记录每个数字出现的次数,一旦发现某一个数字的出现次数超过一半了,就返回。可以采用哈希表记录每个数字出现的次数。算法的时间复杂度是O(n),空间复杂度也是O(n)。然而,该方法只能作为和面试官开聊的开场白,要是作为最终解法就必挂无疑了。
2、基于快速排序的方法:经典的快速排序算法中的partition函数每次会把数组分成两个部分,并把一个值排在正确的位置上。而如果这个位置刚好在n/2处,那么这个数字必然是超过n/2次的数。这种方法同样可以处理寻求第K个的数。该方法的空间复杂度是O(1),但是时间复杂度最坏情况下可能达到O(n^2),平均复杂度是O(nlogn),相当于快速排序了。不过这里基于partition的思想很重要。
3、Moore投票法:设置一个计数器,并维护一个当前出现次数最多的数。在遍历数组的过程中,如果所遍历的数和当前数相等,则计数器加1,否则计数器减1。一旦发现计数器为0,则更新当前数。由于majority element的出现次数大于所有其它数的出现次数之和,所以当遍历完成数组之后,当前数必然是majority element。该算法的时间复杂度是O(n),空间复杂度是O(1),是该问题的最优解和正解。
代码:
1、暴力法:
class Solution {
public:
int majorityElement(vector<int>& nums) {
std::unordered_map<int, int> digits_map;
for (int i = 0; i < nums.size(); ++i) {
if (++digits_map[nums[i]] > nums.size() / 2) {
return nums[i];
}
}
return -1;
}
};
2、基于快速排序的方法:
class Solution {
public:
int majorityElement(vec
b16e
tor<int>& nums) {
if (nums.size() == 0) { // special case
return -1;
}
int start = 0, end = nums.size() - 1;
int index = partition(nums, start, end);
while(index != (nums.size() / 2)) {
if(index > nums.size()/2) { // majority element will certainly be in the left part
end = index - 1;
index = partition(nums, start, end);
}
else if(index < nums.size()/2) { // majority element will certainly be in the right part
start = index + 1;
index = partition(nums, start, end);
}
}
return nums[nums.size()/2];
}
private:
int partition(vector<int>& nums, int begin, int end) {
int value = nums[begin];
while(begin < end) {
while(begin < end && value < nums[end]) {
--end;
}
if(begin < end) {
nums[begin++] = nums[end];
}
while(begin < end && value > nums[begin]) {
++begin;
}
if(begin < end) {
nums[end--] = nums[begin];
}
}
nums[begin] = value;
return begin;
}
};
3、Moore投票法:
Given an array of size n, find the majority element. The majority element is the element that appears more than
⌊ n/2 ⌋times.
You may assume that the array is non-empty and the majority element always exist in the array.
思路:
虽然这道题目的官方难度是easy级别,但我感觉这道题目还是值得好好讨论一下,因为这里面可能会涉及到几个很不错的思想和算法。
1、暴力法:就是扫描数组,并记录每个数字出现的次数,一旦发现某一个数字的出现次数超过一半了,就返回。可以采用哈希表记录每个数字出现的次数。算法的时间复杂度是O(n),空间复杂度也是O(n)。然而,该方法只能作为和面试官开聊的开场白,要是作为最终解法就必挂无疑了。
2、基于快速排序的方法:经典的快速排序算法中的partition函数每次会把数组分成两个部分,并把一个值排在正确的位置上。而如果这个位置刚好在n/2处,那么这个数字必然是超过n/2次的数。这种方法同样可以处理寻求第K个的数。该方法的空间复杂度是O(1),但是时间复杂度最坏情况下可能达到O(n^2),平均复杂度是O(nlogn),相当于快速排序了。不过这里基于partition的思想很重要。
3、Moore投票法:设置一个计数器,并维护一个当前出现次数最多的数。在遍历数组的过程中,如果所遍历的数和当前数相等,则计数器加1,否则计数器减1。一旦发现计数器为0,则更新当前数。由于majority element的出现次数大于所有其它数的出现次数之和,所以当遍历完成数组之后,当前数必然是majority element。该算法的时间复杂度是O(n),空间复杂度是O(1),是该问题的最优解和正解。
代码:
1、暴力法:
class Solution {
public:
int majorityElement(vector<int>& nums) {
std::unordered_map<int, int> digits_map;
for (int i = 0; i < nums.size(); ++i) {
if (++digits_map[nums[i]] > nums.size() / 2) {
return nums[i];
}
}
return -1;
}
};
2、基于快速排序的方法:
class Solution {
public:
int majorityElement(vec
b16e
tor<int>& nums) {
if (nums.size() == 0) { // special case
return -1;
}
int start = 0, end = nums.size() - 1;
int index = partition(nums, start, end);
while(index != (nums.size() / 2)) {
if(index > nums.size()/2) { // majority element will certainly be in the left part
end = index - 1;
index = partition(nums, start, end);
}
else if(index < nums.size()/2) { // majority element will certainly be in the right part
start = index + 1;
index = partition(nums, start, end);
}
}
return nums[nums.size()/2];
}
private:
int partition(vector<int>& nums, int begin, int end) {
int value = nums[begin];
while(begin < end) {
while(begin < end && value < nums[end]) {
--end;
}
if(begin < end) {
nums[begin++] = nums[end];
}
while(begin < end && value > nums[begin]) {
++begin;
}
if(begin < end) {
nums[end--] = nums[begin];
}
}
nums[begin] = value;
return begin;
}
};
3、Moore投票法:
class Solution { public: int majorityElement(vector<int>& nums) { if(nums.size() == 0) { return -1; } int num = nums[0], count = 1; for(int i = 1; i < nums.size(); ++i) { if(nums[i] == num) { ++count; } else { --count; if(count == 0) { num = nums[i]; count = 1; } } } return num; } };
相关文章推荐
- LeetCode 169. Majority Element 解题报告
- 【LeetCode】169. Majority Element(Easy)解题报告
- [leetcode] 169. Majority Element 解题报告
- LeetCode 169. Majority Element and LeetCode 229. Majority Element II解题报告
- leetcode解题方案--169--majority element
- 【LeetCode】Majority Element 解题报告
- LeetCode-Majority Element -解题报告
- leetcode解题报告(21):Majority Element
- Leetcode解题笔记 169.Majority Element [Easy]
- LeetCode 169. Majority Element解题方法
- LeetCode-Majority Element II-解题报告
- LeetCode169. Majority Element
- 【LeetCode】Kth Smallest Element in a BST 解题报告
- [LeetCode169]Majority Element
- leetcode 169 Majority Element 冰山查询
- LeetCode:169. Majority Element
- [leetcode] 169. Majority Element
- 【LeetCode】169.Majority Element (Easy)
- [LeetCode]169. Majority Element(多数元素)
- [LeetCode][169][Majority Element]