Python 基础算法——多数元素

14. 多数元素

给定一个大小为 n 的数组 nums ,返回其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。

你可以假设数组是非空的,并且给定的数组总是存在多数元素。

示例:

输入:nums = [3,2,3]
输出:3

常用的算法分别是:函数法 Counter简单数学思维法投票法字典法排序法

函数法 Counter:

使用 Counter 函数计算多数元素的代码思路是:

  1. 使用 Counter 统计数组 nums 中每个元素出现的次数
  2. 将 nums 转换成集合 set,如果 set 的长度不超过 nums 长度的一半,则说明存在多数元素
  3. 通过 max() 和 key 参数,找到出现次数最多的元素,即为多数元素
# 函数法 Counter    时间复杂度:O(n)    空间复杂度:O(n)
def majority_element1(nums):
    dict = Counter(nums)
    # 返回出现次数最多的那个元素
    return max(dict.keys(), key = dict.get)

时间复杂度: O(n),遍历数组统计元素次数为 O(n),,set 操作为 O(n),找到出现最多的元素为 O(n),总体为线性复杂度。

空间复杂度: O(n),使用字典统计数值次数需要线性大小的额外空间。

简单数学思维法:

使用简单数学思维来判断多数元素的代码思路是:

  1. 计算数组长度 n
  2. 遍历数组中的每个元素 i
  3. 使用生成器表达式统计 i 在数组中出现的次数 count
  4. 如果 count 大于或等于 n的一半,则 i 是多数元素
# 简单数学思维法    时间复杂度:O(n**2)    空间复杂度:O(1)
def majority_element2(nums):
    n = len(nums)

    for i in nums:
        # 当element等于i,返回1,将返回的1累加统计num的出现次数
        count = sum(1 for element in nums if element == i)
        if count >= math.ceil(n/2):
            return i

时间复杂度:O(n^2) ,两层遍历,外层遍历数组元素,内层遍历进行统计计数,时间复杂度是平方级的。

空间复杂度:O(1) ,只需要常数级别的额外空间。

投票法:

使用投票算法求多数元素的代码思路是:

  1. 先判断数组是否存在多数元素
  2. 设置一个major变量记录当前可能的多数元素,count变量记录major出现的次数
  3. 遍历数组,如果遇到与major相同的元素,count++,否则count--
  4. 如果count变为0,则major更新为当前元素,count重置为1
  5. 遍历结束后,major就是多数元素
# 投票法    时间复杂度:O(n)    空间复杂度:O(1)
def majority_elements3(nums):
    major = count = 0
    for n in nums:
        if count == 0:
            major = n
        if n == major:
            count += 1
        else:
            count -= 1
    
    return major

时间复杂度:O(n) ,只需要遍历一次数组即可得到结果,时间复杂度为线性阶。

空间复杂度:O(1) ,只需要两个额外变量major和count,空间复杂度为常数级别。

字典法:

使用字典统计计数的方法的算法思路是:

  1. 用一个字典dict来统计每个元素出现的次数
  2. 遍历数组nums,将每个元素num作为dict的键
  3. 如果num已经在dict中了,则对应的值+1,表示该元素出现次数加1
  4. 如果num不在dict中,则添加入dict,并将出现次数初始化为1
  5. 遍历dict中的键值对,如果某个元素的出现次数count大于数组长度的一半,则它就是多数元素
  6. 返回该元素
# 字典法    时间复杂度:O(n)    空间复杂度:O(n)
def majority_element4(nums):
    dict = {}
    for num in nums:
        if num in dict:
            dict[num] += 1
        else:
            dict[num] = 1
    # 遍历字典dict的所有键值对
    for num, count in dict.items():
        if count > len(nums) // 2:
            return num

时间复杂度: O(N),需要遍历一遍数组统计元素频率,然后遍历一遍字典找到多数元素,总体上是线性时间复杂度。

空间复杂度: O(N),需要一个大小为 N 的字典来存储元素频率,因此需要线性的额外空间。

排序法:

使用排序的方法的算法思路是:

  1. 首先对数组nums进行排序
  2. 由于多数元素出现的次数大于数组长度的一半
  3. 排序后,数组中间位置的元素出现次数一定会超过数组长度的一半
  4. 直接返回排序后数组中mid索引位置的元素,即为多数元素。
# 排序法    时间复杂度:O(nlogn)    空间复杂度:O(1)
def majority_element5(nums):
    nums.sort()
    return nums[len(nums) // 2]

时间复杂度: O(NlogN),主要消耗在排序算法上的时间。

空间复杂度: O(1),直接在原数组上进行排序,没有占用额外空间。

题目来源:力扣

你可能感兴趣的:(数据结构,python,算法)