leetcode 229. Majority Element II 摩尔投票法 Moore Voting + 要记住验证投票结果哦

深碍√TFBOYSˉ_ 2022-06-08 12:08 295阅读 0赞

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.

题意很简单,就是寻找大于三分之一的元素,最简单的就是HashMap计数,这个很快。

建议和这道题leetcode 169. Majority Element 一起学习,这道题采用的就是HashMap计数。

那就是摩尔投票法 Moore Voting,这种方法在之前那道题Majority Element 求众数中也使用了。题目中给了一条很重要的提示,让我们先考虑可能会有多少个众数,经过举了很多例子分析得出,任意一个数组出现次数大于n/3的众数最多有两个,具体的证明我就不会了,我也不是数学专业的。

那么有了这个信息,我们使用投票法的核心是找出两个候选众数进行投票,需要两遍遍历, 第一遍历找出两个候选众数,第二遍遍历重新投票验证这两个候选众数是否为众数即可,选候选众数方法和前面那篇Majority Element 求众数一样,由于之前那题题目中限定了一定会有众数存在,故而省略了验证候选众数的步骤,这道题却没有这种限定,即满足要求的众数可能不存在,所以要有验证。

摩尔投票法的基本思想很简单,在每一轮投票过程中,从数组中找出一对不同的元素,将其从数组中删除。这样不断的删除直到无法再进行投票。

代码如下:

  1. import java.util.ArrayList;
  2. import java.util.List;
  3. /*
  4. * 摩尔投票方法解决,记住吧
  5. *
  6. * http://mabusyao.iteye.com/blog/2223195
  7. *
  8. * 那就是摩尔投票法 Moore Voting,这种方法在之前那道题Majority Element 求众数中也使用了。
  9. * 题目中给了一条很重要的提示,让我们先考虑可能会有多少个众数,经过举了很多例子分析得出,
  10. * 任意一个数组出现次数大于n/3的众数最多有两个,具体的证明我就不会了,我也不是数学专业的。
  11. * 那么有了这个信息,我们使用投票法的核心是找出两个候选众数进行投票,需要两遍遍历,
  12. * 第一遍历找出两个候选众数,第二遍遍历重新投票验证这两个候选众数是否为众数即可,
  13. * 选候选众数方法和前面那篇Majority Element 求众数一样,由于之前那题题目中限定了一定会有众数存在,
  14. * 故而省略了验证候选众数的步骤,这道题却没有这种限定,即满足要求的众数可能不存在,所以要有验证。
  15. *
  16. *
  17. * 摩尔投票法的基本思想很简单,在每一轮投票过程中,从数组中找出一对不同的元素,
  18. * 将其从数组中删除。这样不断的删除直到无法再进行投票,
  19. *
  20. * */
  21. public class Solution
  22. {
  23. public List<Integer> majorityElement(int[] nums)
  24. {
  25. List<Integer> res=new ArrayList<Integer>();
  26. if(nums==null || nums.length<=0)
  27. return res;
  28. else if(nums.length==1)
  29. {
  30. res.add(nums[0]);
  31. return res;
  32. }
  33. int m1=nums[0] , m2=0;
  34. int count1=1 , count2=0;
  35. for(int i=1;i<nums.length;i++)
  36. {
  37. if(nums[i]==m1)
  38. count1++;
  39. else if(nums[i]==m2)
  40. count2++;
  41. else if(count1==0)
  42. {
  43. m1=nums[i];
  44. count1=1;
  45. }else if(count2==0)
  46. {
  47. m2=nums[i];
  48. count2=1;
  49. }else
  50. {
  51. count1--;
  52. count2--;
  53. }
  54. }
  55. //验证检查过程
  56. count1=0;
  57. count2=0;
  58. for(int i=0;i<nums.length;i++)
  59. {
  60. if(nums[i]==m1)
  61. count1++;
  62. else if(nums[i]==m2)
  63. count2++;
  64. }
  65. if(count1>(nums.length/3))
  66. res.add(m1);
  67. if(count2>(nums.length/3))
  68. res.add(m2);
  69. return res;
  70. }
  71. }

下面是C++的做法,做简单的做法就是使用map遍历,其实还有一个更加简单的做法,就是摩尔投票法,这个做法很棒,值得学习

代码如下:

  1. #include <iostream>
  2. #include <vector>
  3. #include <map>
  4. #include <unordered_map>
  5. #include <set>
  6. #include <unordered_set>
  7. #include <queue>
  8. #include <stack>
  9. #include <string>
  10. #include <climits>
  11. #include <algorithm>
  12. #include <sstream>
  13. #include <functional>
  14. #include <bitset>
  15. #include <numeric>
  16. #include <cmath>
  17. #include <regex>
  18. using namespace std;
  19. class Solution
  20. {
  21. public:
  22. vector<int> majorityElement(vector<int>& a)
  23. {
  24. vector<int> res;
  25. if (a.size() <= 0)
  26. return res;
  27. int m1 = INT_MIN, m2 = INT_MIN, count1 = 0, count2 = 0;
  28. for (int i : a)
  29. {
  30. if (i == m1)
  31. count1++;
  32. else if (i == m2)
  33. count2++;
  34. else if (count1==0)
  35. {
  36. m1 = i;
  37. count1 = 1;
  38. }
  39. else if (count2==0)
  40. {
  41. m2 = i;
  42. count2 = 1;
  43. }
  44. else
  45. {
  46. count1--;
  47. count2--;
  48. }
  49. }
  50. count1 = count2 = 0;
  51. for (int i : a)
  52. {
  53. if (i == m1)
  54. count1++;
  55. else if (i == m2)
  56. count2++;
  57. }
  58. if (count1 >= a.size() / 3)
  59. res.push_back(m1);
  60. if (count2 >= a.size() / 3)
  61. res.push_back(m2);
  62. return res;
  63. }
  64. };
  65. vector<int> majorityElementByMap(vector<int>& nums)
  66. {
  67. vector<int> res;
  68. map<int, int> mmp;
  69. for (int a : nums)
  70. {
  71. if (mmp.find(a) == mmp.end())
  72. mmp[a] = 1;
  73. else
  74. mmp[a] += 1;
  75. }
  76. map<int, int>::iterator i = mmp.begin();
  77. for (; i != mmp.end(); i++)
  78. {
  79. if (i->second > nums.size() / 3)
  80. res.push_back(i->first);
  81. }
  82. return res;
  83. }
  84. };

发表评论

表情:
评论列表 (有 0 条评论,295人围观)

还没有评论,来说两句吧...

相关阅读

    相关 投票

    背景: leetcode 169题求一个数组中,出现次数大于 n/2;的元素 如果在一个遍历中解决这个问题?? 答案就是摩尔投票法。 摩尔投票法:用一个计数器,每次当计

    相关 投票

    提问: 给定一个int型数组,找出该数组中出现次数大于数组长度一半的int值。 解决方案: 遍历该数组,统计每个int值出现次数,再遍历该数组,找出出现次数大于数组长度一半的

    相关 投票

    摩尔投票 问题背景 在一个大厅中,每位票民手中都有一张票他可以给自己喜欢的候选人偷一票,我们现在已知每个票民的投票结果。 问:如何通过一次遍历找到票数超过一半的

    相关 8-1投票

    > 不同的数字进行一对一“火并”(原理不再赘叙), > 如果存在众数,“火并”之后留下了的一定是,最后还需要进行验证。 先上模板:         ![watermar