[LeetCode]17. Majority Element主元素
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.
解法1:将数组排序,取位于数组中间的元素即可。时间复杂度O(nlogn)。
class Solution { public: int majorityElement(vector<int>& nums) { sort(nums.begin(), nums.end()); return nums[nums.size() >> 1]; } };
解法2:一个最直接的想法即是统计每个元素出现的次数,然后选出出现次数最多的那个即可。时间复杂度O(n)。
class Solution { public: int majorityElement(vector<int>& nums) { int n = nums.size(); map<int, int> mii; for (int i = 0; i < n; i++) mii[nums[i]]++; map<int, int>::iterator iter = mii.begin(); int majElem = 0; int maxCnt = 0; for (; iter != mii.end(); ++iter) { if (iter->second > maxCnt) { majElem = iter->first; maxCnt = iter->second; } } return majElem; } };
解法3:因为这个元素出现的次数超过整个数组长度的一半,所以若数组中所有的这个元素若集中在一起,则数组中间的元素必定是这个元素。因此可以考虑快速排序的Partition算法:若某次Partition选出的Pivot在Partition后位于数组中间,则即是这个出现次数超过一半的元素。时间复杂度O(n)。
class Solution { public: int majorityElement(vector<int>& nums) { int n = nums.size(); int index = 0; int middle = n >> 1; int start = 0; int end = n - 1; while (index != middle) { if (index > middle) { end = index - 1; index = partition(nums, n, start, end); } else { start = index + 1; index = partition(nums, n, start, end); } } return nums[middle]; } private: int partition(vector<int>& nums, int n, int low, int high) { int key = nums[0]; while (low < high) { while (low < high && nums[high] >= key) high--; if (low < high) { nums[low] = nums[high]; low++; } while (low < high && nums[low] <= key) low++; if (low < high) { nums[high] = nums[low]; high--; } } nums[low] = key; return low; } };
上面的程序在输入数组特别大时会出现Time Limit Exceeded。在Majority Element次数特别多时会做很多无用操作。
解法4:数组中一个元素出现次数超过数组长度的一半,也就是说它出现的次数比其他所有数字出现的次数的和还要多。因此可以在遍历时保存两个值:一个是数组中的一个数字,一个是次数。当遍历到下一个数字的时候,如果它和之前保存的数字相同,则次数加1;否则次数减1。如果次数为零,则保存下一个数字,并将次数设为1.最后要找的数字肯定是最后一次把次数设为1时对应的元素。时间复杂度为O(n)。
class Solution { public: int majorityElement(vector<int>& nums) { int n = nums.size(); int majElem = nums[0]; int cnt = 1; for(int i = 1; i < n; i++) { if(cnt == 0) { majElem = nums[i]; cnt = 1; } else if(nums[i] == majElem) cnt++; else cnt--; } return majElem; } };