[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;
    }
};
原文地址:https://www.cnblogs.com/aprilcheny/p/4860451.html