zoukankan      html  css  js  c++  java
  • Majority Element(169) && Majority Element II(229)

    寻找多数元素这一问题主要运用了:Majority Vote Alogrithm(最大投票算法)
    1.Majority Element

         1)description

            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.

            注意3点:这里的多数元素必须严格大于⌊ n/2 ⌋(向下取整)、题目假定数组非空、假定最大元素一定存在(并且我们可以知道满足要求的元素仅1个)。

            eg:[1,2,7,2,2,5,10,2,2]   n=9  最多数元素为2,因为它出现次数为5>⌊ 9/2 ⌋=4.

         2)solutions

           链接中有leetcoder的六种方案,例如最直观的哈希表:map遍历时通过对相同数组元素逐一累加可以筛选出满足条件的元素,这一方案对Majority Element II也适用;或者通过对数组先排序,那么取出数组索引为⌊ n/2 ⌋的元素即可;又有随机抽取数组中的元素然后求其出现次数,由于最多数元素为⌊ n/2 ⌋个,所以最糟情况下猜了⌊ n/2 ⌋次;分治法;最大投票算法。                              

         3)最大投票算法原理:

            遍历数组,当碰到两个不一样的数字时,将这两个数字同时丢弃,这两个数字中可能有一个为 Majority Element,也可能两个都不为Majority Element.因为k 大于 n/2,所以在最差情况下(每次移除不同数字时都包含一个Majority Element),我们仍然能够保证最后得到的数字是Majority Element.总之:在原序列中去除两个不同的元素后,在原序列中的多数元素在新序列中还是多数元素。                     

           根据《算法设计技巧与分析》书中的算法可以写出如下非递归代码(书中为递归版本并且附有检查候选的最多数元素是否存在):

    class Solution {
    public:
        int majorityElement(vector<int>& nums) {
            int j,candidate,count;                //candidate代表候选解即最多数元素,count代表票数
            for (j = 0; j < nums.size(); j++){
               candidate = nums[j]; count = 1;   //起初假定第一个元素即为candidate且票数为1,当票数count=0时就换candidate
               while (j < nums.size() - 1 && count>0){
                    j = j + 1;
                    if (nums[j] == candidate) count++;  //当下一个元素与candidate相等时票数+1
                    else count--;                       //否则票数-1
                 }
             }
            return c;
        }
    };

     下面代码和上面完全一样,只是更直观一点:

    class Solution {
    public:
        int majorityElement(vector<int>& nums) {
            int candidate, count = 0, n = nums.size();
            for (int i = 0; i < n; i++) {
                if (count==0) {                //票数为0则换candidate,换了candidate票数就得变为1
                    candidate = nums[i];
                    count = 1;
                }
                else if(nums[i] == candidate)  //下一个元素和candidate相等时票数+1
                     count++;
                else
                     count--;                  //不相等票数-1
            }
            return candidate;
        }
    };

          总结:因为数组个数为n,且最多数元素个数>⌊ n/2 ⌋,所以有且只有1个元素满足条件,所以设置了一个candidate和一个计票器count。而 Majority Element II要求是最多数元素个数>⌊ n/3 ⌋,所以至多有2个元素满足要求,所以需要设置两个candidate和两个计票器count

    2.Majority Element II

         1)description: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.

         2)思路:我们需要找到三个不同的数字,然后抛弃掉这三个数字:首先要判断是否等于candidate,如果等于candidate那么对应的 candidate 必须加一等待其他的数字来消除它,当有一个 candidate 的 count 为 0 时,说明该 candidate 已经全部被消除,我们需要设定新的 candidate 数字。当一个数字不等于两个 candidate,同时两个 candidate 的 count 都不为零。这意味着当前这个数字就是这两个candidate 等待的第三个数字。于是这三个数字被移除,同时它们的的 count 都要减一。                                 

          eg:[2,1,1,4,6,1,10]       n=7   元素1的个数为3>⌊ 7/3 ⌋=2

                 [2,1,1,1,10,2,2,1]    n=8   元素1个数为4>⌊ 8/3 ⌋=2,元素2的个数为3>⌊ 8/3 ⌋=2

          python代码:

    class Solution(object):
        def majorityElement(self, nums):
            """
            :type nums: List[int]
            :rtype: List[int]
            """
            if not nums:
                return []
            count1, count2, candidate1, candidate2 = 0, 0, 0, 0       //初始化两个candidate和两个count
            for n in nums:
                if n == candidate1:                      //注意这里的元素值相等和count为0的判断顺序与问题一中正好相反
                   count1 += 1                           //这里先判断元素值与candidate是否相等
                elif n == candidate2:
                   count2 += 1
                elif count1 == 0:                        //再判断count是否为0
                   candidate1, count1 = n, 1
                elif count2 == 0:
                   candidate2, count2 = n, 1
                else:
                   count1, count2 = count1 - 1, count2 - 1
            return [n for n in (candidate1, candidate2) if nums.count(n) > len(nums) // 3]

     参考:segmentFault

  • 相关阅读:
    pads layout模块复用-两个不同功能的复用模块功能
    摘抄:一个电容都能讲得如此全面实用,不分享就太可惜了!
    layout需要非常了解清楚的内容
    摘抄:一篇文章看看能不能讲透“阻抗匹配”
    python2.7/3.7安装NumPy函数库的一种方法及小心得
    3.C#基础之基本概念(完成)
    2.C#基础之词法结构(完成)
    .NET、.NET框架、ASP.NET和C#的关系(完成)
    1.C#基础之简介(完成)
    2.LINQ(新手写的!新手写的!新手写的!)(未完成)
  • 原文地址:https://www.cnblogs.com/king-lps/p/6395058.html
Copyright © 2011-2022 走看看