LeetCode练习 | Majority Element

Problem:
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.

Solution 1:

虽然是按照分类选择的,但首先想到的并不是分治算法。这里也先写下来,以便进行比较。

算法分为两部分:第一部分遍历向量用map记录每个元素出现的次数,遍历的复杂度为O(n),map的find方法复杂度为O(logm),m为不同key数目,总复杂度为O(nlogm)。第二部分再次遍历,找到出现次数大于n/2的元素并返回,时间复杂度为O(n)。因此算法整体时间复杂度为O(nlogn),使用了map,空间复杂度为O(n),代码如下:

#include <map>
using namespace std;

class Solution {
public:
    int majorityElement(vector<int>& nums) {

        map<int, int> ans;
        for (int i = 0; i < nums.size(); ++i){

            if (ans.find(nums[i])==ans.end())
                ans[nums[i]] = 1;
            else
                ans[nums[i]]++;
        }

        for (int i = 0; i < nums.size(); ++i){

            if (ans[nums[i]] > nums.size()/2)
                return nums[i];
        }
        return 0; // 有约束条件ME一定存在,所以可返回任意值,否则要对不存在的情况特殊处理
    }
};

LeetCode上的测试时间为39ms. 在某些情况下,比如1,1,2,2,3,3,3,3,3,第二次遍历的过程中可能重复比较同一个非ME的key的value. 因为结果唯一,也可以用multimap,和map的查找复杂度相当。此时第二部分时间复杂度变为O(m),对给定测试用例有一定优化,36ms,但算法复杂度仍为O(nlogm),只是实现略有不同.

#include <map>
using namespace std;

class Solution {
public:
    int majorityElement(vector<int>& nums) {

        multimap<int, int> ans;
        for (int i = 0; i < nums.size(); ++i){

            if (ans.find(nums[i])==ans.end())
                ans.insert(make_pair(nums[i], 1));
            else
                (ans.find(nums[i]))->second++;
        }

        for (multimap<int,int>::iterator i = ans.begin(); i != ans.end(); i++){

            if ((*i).second > nums.size()/2)
                return (*i).first;
        }
        return 0;
    }
};

Solution 2:

因为ME数目一定大于n/2,所以可以将向量排序,中值一定是ME。调用sort函数,其底层是一种混合排序;自己写可以使用归并排序(分治算法)或者堆排序,时间复杂度都为O(nlogn). LeetCode测试时间为36ms.

#include <algorithm>

class Solution {
public:
    int majorityElement(vector<int>& nums) {

        sort(nums.begin(),nums.end());
        return nums[nums.size()/2];
    }
};

Solution 3:

在Discuss中学习到了很巧妙的算法Boyer–Moore majority vote algorithm,本问题中时间复杂度为O(n),空间复杂度为O(1).

算法将每对相邻元素进行比较,count=0时更新maj,count++;元素相同时count++;不同时count–。无论从ME还是非ME元素开始执行算法,由于ME数多于非ME,都有一个时间点t,t以后的maj一直是ME. LeetCode测试时间为16ms.

class Solution {
public:
    int majorityElement(vector<int>& nums) {

        int maj = nums[0], count = 1;
        for (int i = 1; i < nums.size(); ++i){

            if (count == 0){
                maj = nums[i];
                count++;
            }
            else if (nums[i] == maj)
                count++;
            else
                count--;
        }
        return maj;
    }
};

原代码链接 https://discuss.leetcode.com/topic/8692/o-n-time-o-1-space-fastest-solution
算法链接 https://en.wikipedia.org/wiki/Boyer%E2%80%93Moore_majority_vote_algorithm

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值