• [LeetCode] Majority Element


    Well, if you have got this problem accepted, you may have noticed that there are 7 suggested solutions for this problem. The following passage will implement 6 of them except the O(n^2)brute force algorithm.

    Hash Table

    The hash-table solution is very straightforward. We maintain a mapping from each element to its number of appearances. While constructing the mapping, we update the majority element based on the max number of appearances we have seen. Notice that we do not need to construct the full mapping when we see that an element has appeared more than n / 2 times.

    The code is as follows, which should be self-explanatory.

     1 class Solution {
     2 public:
     3     int majorityElement(vector<int>& nums) {
     4         unordered_map<int, int> counts;
     5         int n = nums.size();
     6         for (int i = 0; i < n; i++)
     7             if (++counts[nums[i]] > n / 2)
     8                 return nums[i];
     9     }
    10 };

    Sorting

    Since the majority element appears more than n / 2 times, the n / 2-th element in the sortednums must be the majority element. This can be proved intuitively. Note that the majority element will take more than n / 2 positions in the sorted nums (cover more than half of nums). If the first of it appears in the 0-th position, it will also appear in the n / 2-th position to cover more than half of nums. It is similar if the last of it appears in the n - 1-th position. These two cases are that the contiguous chunk of the majority element is to the leftmost and the rightmost in nums. For other cases (imagine the chunk moves between the left and the right end), it must also appear in the n / 2-th position.

    The code is as follows, being very short if we use the system sort.

    1 class Solution {
    2 public:
    3     int majorityElement(vector<int>& nums) {
    4         sort(nums.begin(), nums.end());
    5         return nums[nums.size() / 2];
    6     }
    7 };

    Randomization

    This is a really nice idea and works pretty well (16ms running time on the OJ, almost fastest among the C++ solutions). The proof is already given in the suggested solutions.

    The code is as follows, randomly pick an element and see if it is the majority one.

     1 class Solution {
     2 public:
     3     int majorityElement(vector<int>& nums) {
     4         int n = nums.size();
     5         srand(unsigned(time(NULL)));
     6         while (true) {
     7             int idx = rand() % n;
     8             int candidate = nums[idx];
     9             int counts = 0; 
    10             for (int i = 0; i < n; i++)
    11                 if (nums[i] == candidate)
    12                     counts++;
    13             if (counts > n / 2) return candidate;
    14         }
    15     }
    16 };

    Divide and Conquer

    This idea is very algorithmic. However, the implementation of it requires some careful thought about the base cases of the recursion. The base case is that when the array has only one element, then it is the majority one. Moreover, this solution is relatively slow in practice.

     1 class Solution {
     2 public:
     3     int majorityElement(vector<int>& nums) {
     4         return majority(nums, 0, nums.size() - 1);
     5     }
     6 private:
     7     int majority(vector<int>& nums, int left, int right) {
     8         if (left == right) return nums[left];
     9         int mid = left + ((right - left) >> 1);
    10         int lm = majority(nums, left, mid);
    11         int rm = majority(nums, mid + 1, right);
    12         if (lm == rm) return lm;
    13         return counts(nums, lm) > counts(nums, rm) ? lm : rm;
    14     }
    15     int counts(vector<int>& nums, int elem) {
    16         int cnt = 0;
    17         for (int i = 0; i < int(nums.size()); i++)
    18             if (nums[i] == elem) cnt++;
    19         return cnt;
    20     }
    21 };

    Moore Voting Algorithm

    A brilliant and easy-to-implement algorithm! It also runs very fast, about 20ms.

     1 class Solution {
     2 public:
     3     int majorityElement(vector<int>& nums) {
     4         int major, counts = 0, n = nums.size();
     5         for (int i = 0; i < n; i++) {
     6             if (!counts) {
     7                 major = nums[i];
     8                 counts = 1;
     9             }
    10             else counts += (nums[i] == major) ? 1 : -1;
    11         }
    12         return major;
    13     }
    14 };

    Bit Manipulation

    Another nice idea! The key lies in how to count the number of 1's on a specific bit. Specifically, you need a mask with a 1 on the i-the bit and 0 otherwise to get the i-th bit of each element in nums. The code is as follows.

     1 class Solution {
     2 public:
     3     int majorityElement(vector<int>& nums) {
     4         int major = 0, n = nums.size();
     5         for (int i = 0, mask = 1; i < 32; i++, mask <<= 1) {
     6             int bitCounts = 0;
     7             for (int j = 0; j < n; j++) {
     8                 if (nums[j] & mask) bitCounts++;
     9                 if (bitCounts > n / 2) {
    10                     major |= mask;
    11                     break;
    12                 }
    13             }
    14         } 
    15         return major;
    16     } 
    17 };
  • 相关阅读:
    如何利用京东云的对象存储(OSS)上传下载文件
    2017年4月8日Office 365 使用CSV文件导入邮件组
    在Office 365 的如何给管理员赋予查看所有人邮箱的权限的Powershell
    Office 365 Powershell 连接命令
    Office365创建通讯组
    国际版删除域名的步骤
    如何停止AAD服务
    导出Office365中的组及成员
    AWS/阿里/Azure,云厂商价格大PK
    OA系统与Exchange 日历打通
  • 原文地址:https://www.cnblogs.com/jcliBlogger/p/4609920.html
Copyright © 2020-2023  润新知