Majority Number I II III

Majority Number I II III

一个寻众数的问题。
多数投票算法 Boyer–Moore majority vote algorithm


Majority Number

Leetcode:169. Majority Element
Lintcode:46. Majority Number

Given an array of integers, the majority number is the number that occurs more than half of the size of the array. Find it.

Notice
You may assume that the array is non-empty and the majority number always exist in the array.

本题是一个求众数问题,也是一个投票问题。需要找到数组中出现次数超过半数的元素。
本问题可以用贪心方法求解。由于本题中的众数出现次数超过 n/2 ⌊ n / 2 ⌋

可以将本问题看做超过半数有效的投票问题。任取数组 A A 中一个元素Ai将其看做目标众数的候选值,其形成候选数组 B B 加入Ai

Ai A i 是否为结果的关键是,候选数组 B B 能否构成以Ai为众数的 A A 的子数组。

这时,考虑Ajij Ai A i 的值。有两种情况。

  1. Ai=Aj A i = A j
    此时将 Aj A j 加入数组 B B

  2. AiAj
    这时可以看出在数组 A A 中删去 AiAj并不影响数值 AiAj A i , A j 在数组中是众数的可能性。
    因为,众数在数组中一定出现半数以上。
    但删的是两个不相同元素,假设其中一个是正确答案,则它与非众数元素同时减少一个,答案元素仍超过半数。
    如果,两个都不是正确答案,删去这两个元素。则正确答案占比仍超过半数。
    综上所述,这时抛弃 Aj A j 并删除 B B 中的一个 Ai
    如果, 这时数组 B B 被删空了,就再从数组 A的剩余元素中选一个候选重复上述工作最后 B B 中剩余元素即为最终答案。

我们可以看出数组 B可以简化为 Ai A i 的计数,添加为 + + ,删除为

class Solution {
public:
    int majorityElement(vector<int>& nums) {
        int candidate = nums[0];    //指定一个候选元素
        int count = 1;              //数组B计数开始
        for (int i = 1 ; i < nums.size() ; i ++) {
            if (candidate == nums[i])
                //如果与候选元素相同,对数组B进行添加
                count++;
            else
                //如果与候选元素不同,对数组B进行删去
                count--;
            if (count == 0) {
                //如果数组B已被删空则重新选定一个候选元素
                candidate = nums[++i];
                count++;
            }
        }
        return candidate;
    }
};

Majority Number II

Leetcode:229. Majority Element II
Lintcode:47. Majority Number II

Given an integer array of size n, find all elements that appear more than ⌊ n/3 ⌋ times. The algorithm should run in linear time and in O(1) space.

Lintcode:47. Majority Number II Notice
There is only one majority number in the array.

本题是上一题的简单拓展,众数从超过半数变为超过 n/3 ⌊ n / 3 ⌋ 。候选众数变为两个。这时需要对最终得到的候选众数进行验证。

注意到,LeetCode的题中众数不唯一。

class Solution {
public:
    vector<int> majorityElement(vector<int>& nums) {
        //有几个候选众数
        int k = 2;
        //满足是众数的条件
        int floor = nums.size() / 3;
        //建立候选众数的容器
        map<int , int> candidates;
        //进行投票模拟
        for (int i = 0 ; i < nums.size() ; i ++) {
            //如果实际候选数小于应有候选数,加入新的候选数
            if (candidates.size() < k) {
                //如果与已有候选数重复了,已有候选数进行计数添加。否则,添加候选数
                if (candidates.find(nums[i]) != candidates.end())
                    candidates[nums[i]]++;
                else
                    candidates[nums[i]] = 1;
            } else {
                //如果实际候选数等于应有候选数
                if (candidates.find(nums[i]) != candidates.end())
                    //如果与候选数中的其中一个相等,则未破坏子数组的特性,对候选数进行计数添加。
                    candidates[nums[i]]++;
                else
                    //如果与候选数都不相等,则从nums中删去子数组 A_i,A_j,A_k
                    for (auto j = candidates.begin() ; j != candidates.end() ; ) {
                        j->second--;
                        if (j->second == 0)
                            j = candidates.erase(j);
                        else
                            j++;
                    }
            }
        }
        //完成对候选数的验证
        for (auto c = candidates.begin() ; c != candidates.end() ; c ++) {
            c->second = 0;
        }
        for (int a : nums) {
            if (candidates.find(a) != candidates.end())
                candidates[a]++;
        }
        vector<int> res;
        for (auto it : candidates) {
            if (it.second > floor)
                res.push_back(it.first);
        }
        return res;
    }
};

Majority Number III

Lintcode:48. Majority Number III

Given an array of integers and a number k, the majority number is the number that occurs more than 1/k of the size of the array.
Find it.

Notice
There is only one majority number in the array.

本题其实在在上一题中已经给出答案了。

class Solution {
public:
    /*
     * @param nums: A list of integers
     * @param k: An integer
     * @return: The majority number
     */
    int majorityNumber(vector<int> &nums, int k) {
        // write your code here
        unordered_map<int , int> candidate;
        int size = k - 1;
        for (int i = 0 ; i < nums.size() ; i++) {
            if (candidate.size() < size) {
                if (candidate.find(nums[i]) == candidate.end()) {
                    candidate[nums[i]] = 1;
                } else {
                    candidate[nums[i]]++;
                }
            } else {
                if (candidate.find(nums[i]) == candidate.end()) {
                    auto j = candidate.begin();
                    while (true) {
                        if (j == candidate.end()) {
                            break;
                        }
                        (j -> second)--;
                        if (j -> second == 0) {
                            j = candidate.erase(j);
                        } else {
                            j++;
                        }
                    }
                } else {
                    candidate[nums[i]]++;
                }
            }
        }
        for (auto i = candidate.begin() ; i != candidate.end() ; i++) {
            i -> second = 0;
        }
        int max = 0 , res = 0;
        for (int i = 0 ; i < nums.size() ; i++) {
            candidate[nums[i]]++;
            if (candidate[nums[i]] > max) {
                max = candidate[nums[i]];
                res = nums[i];
            }
        }
        return res;
    }
};

class Solution {
public:
    /*
     * @param nums: A list of integers
     * @param k: An integer
     * @return: The majority number
     */
    int majorityNumber(vector<int> &nums, int k) {
        // write your code here
        //满足是众数的条件
        int floor = nums.size() / k;
        //建立候选众数的容器
        map<int , int> candidates;
        //进行投票模拟
        for (int i = 0 ; i < nums.size() ; i ++) {
            //如果实际候选数小于应有候选数,加入新的候选数
            if (candidates.size() < k) {
                //如果与已有候选数重复了,已有候选数进行计数添加。否则,添加候选数
                if (candidates.find(nums[i]) != candidates.end())
                    candidates[nums[i]]++;
                else
                    candidates[nums[i]] = 1;
            } else {
                //如果实际候选数等于应有候选数
                if (candidates.find(nums[i]) != candidates.end())
                    //如果与候选数中的其中一个相等,则未破坏子数组的特性,对候选数进行计数添加。
                    candidates[nums[i]]++;
                else
                    //如果与候选数都不相等,则从nums中删去子数组 A_i,A_j,A_k
                    for (auto j = candidates.begin() ; j != candidates.end() ; ) {
                        j->second--;
                        if (j->second == 0)
                            j = candidates.erase(j);
                        else
                            j++;
                    }
            }
        }
        //完成对候选数的验证
        for (auto c = candidates.begin() ; c != candidates.end() ; c ++) {
            c->second = 0;
        }
        for (int a : nums) {
            if (candidates.find(a) != candidates.end())
                candidates[a]++;
        }
        vector<int> res;
        for (auto it : candidates) {
            if (it.second > floor)
                res.push_back(it.first);
        }
        return res[0];
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值