zoukankan      html  css  js  c++  java
  • [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;
        }
    };
  • 相关阅读:
    在java中有关于反射的皮毛----自己的简略认知
    在java中异常中的题目---重要的一点
    在一个陌生的环境里学习新的-----单例
    在java开发环境中,快捷键的使用及用法
    指针(一)
    #ifdef、#ifndef、#else、#endif执行条件编译
    oc中的数组
    控制循环结构
    oc中的枚举
    oc中类的实例化及方法调用
  • 原文地址:https://www.cnblogs.com/aprilcheny/p/4860451.html
Copyright © 2011-2022 走看看