LeetCode169 Majority Element-python(easy)

题目来源:

https://leetcode.com/problems/majority-element/description/

题目分析:

给定一个n维的数组,寻找出现次数最多的那个元素。那个出现最多的元素至少会在数组中出现一半,要我们求出这个元素。

下面有好几种方法:

1.暴力搜索的方法

  对数组中的元素进行遍历,然后分别求出每个元素出现的次数,如果该次数大于列表的一半,则输出这个数字。其具体代码如下:

class Solution:
    def majorityElement(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        major_num=len(nums)//2   %python3里的“/ "表示 浮点数除法,返回浮点结果;" // "表示整数除法
        for num in nums:
            s=sum(1 for elem in nums if elem==num )  %这里表示的是每次if判断正确就sum+1
            if (s>major_num):
                return num

结果是时间复杂度超过了。

2.HashMap方法

  Hash算法实际上就是利用Key计算位置的算法,它利用了字典键-值对的特性。在这里我们采用了python内置模块collections中的Counter类方法。Collections包含了除了dict,set,list,tuple以外的一些特殊的容器类型。具体可参见文档:http://docs.python.org/2/library/collections.html。下面主要介绍一下我们使用的Counters类。

  Counter类的目的是用来跟踪值出现的次数。它是一个无序的容器类型,以字典的键值对形式存储,其中元素作为key,其计数作为value。计数值可以是任意的Interger(包括0和负数)。Counter类和其他语言的bags或multisets很相似。因此本题的代码可以写成:

class Solution:
    def majorityElement(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        counts=collections.Counter(nums)
       
        return max(counts.keys(),key=counts.get)

为了更好的理解代码,我们可以把上述程序改写为:

import collections
class Solution:
    def majorityElement(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        counts=collections.Counter(nums) %从一个可迭代对象(list,tuple,dict,字符串)创建Counter类
        return max(counts.keys(),key=lambda x:counts.get(x))

Counter类的存储是一个字典,而get方法是字典中用来得到值的。lambda方法定义了一个匿名类,counts.get(x)得到了counts中所有的值,keys代表了counts中所有的键,max函数如果有关键字key,用法就是按照key来选最大值,而key是get函数,得到的是值,因此最后一句话就返回了值最大的key,也就是出现次数最多的数。

3.排序法

 因为出现次数最多的数字占据了整个数组的一半之多,那么将数组进行排序后,其中间的那个数一定就是我们要找的数字。其代码为:

class Solution:
    def majorityElement(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        nums.sort()
        return (nums[len(nums)//2])

4.最大投票算法(需要学习的算法)Moore's voting algorithm

  该算法主要用来解决在元素列表中找到出现元素次数最多的元素。具体可以看http://www.cs.utexas.edu/~moore/best-ideas/mjrty/index.html。算法的思想是:每次都找出一对不同的元素,从数组中删掉,直到数组为空或只有一种元素。

不难证明,如果存在元素e出现频率超过半数,那么数组中最后剩下的就只有e。当然,最后剩下的元素也可能并没有出现半数以上。比如说数组是[1, 2, 3],最后剩下的3显然只出现了1次,并不到半数。排除这种false positive情况的方法也很简单,只要保存下原始数组,最后扫描一遍验证一下就可以了。

因此该程序为:

class Solution {
    public int majorityElement(int[] nums) {
        
        int len = nums.length, candidate=nums[0], count=1;
        
        for(int i=1; i<len; i++) {            
            if(nums[i]==candidate)
                count++;
            else {
                count--;
                if(count==0) {
                    candidate=nums[i];
                    count=1;
                }
            }            
        }        
        return candidate;    
    }
}

如果要采用这个算法,题目中出现次数大于列表的一半是必要条件,因为我们每次在移除时,最坏的情况是每次移除一个出现次数最多的数和一个非目标数,要确保剩下的数为出现次数最多的数,则需要它大于列表的一半。

  关于这个算法的改进与变形,可以参看:https://blog.csdn.net/huanghanqian/article/details/74188349



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值