169_求众数(Majority-Element)

这道题有 5 种方法,8 种实现,详细分析可以看花花酱YouTube 专栏

描述

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

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

示例 1:

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

示例 2:

输入: [2,2,1,1,1,2,2]
输出: 2

解法一:暴力法

思路

遍历数组中的每个元素,统计该元素出现的次数(嵌套遍历),如果该元素出现的次数 \(> \left \lfloor n/2 \right \rfloor\),则该元素就是数组的众数。

Java 实现

class Solution {
public int majorityElement(int[] nums) {
int majorityCount = nums.length / 2;
for (int num1 : nums) {
int count = 0;
for (int num2 : nums) {
if (num2 == num1) {
++count;
}
}
if (count > majorityCount) {
return num1;
}
}
throw new IllegalArgumentException("The array does not contain a majority element!");
}
}

Python 实现

class Solution:
def majorityElement(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
majority_count = len(nums) // 2
for num1 in nums:
count = sum(1 for num2 in nums if num2 == num1)
if count > majority_count:
return num1

复杂度分析

  • 时间复杂度:\(O(n^2)\),其中 \(n\) 表示数组的长度,由于嵌套了两层 for 循环,因此总的时间复杂度是 \(O(n^2)\) 的
  • 空间复杂度:\(O(1)\)

解法二:哈希表

思路

利用哈希表记录数组中元素出现的次数,由于哈希表的插入操作的时间复杂度是 \(O(1)\) 的,所以遍历整个数组统计出现次数的操作的时间复杂度是 \(O(n)\) 的。接着,再遍历一遍哈希表,取出众数。

Java 实现

class Solution {
public int majorityElement(int[] nums) {
Map<Integer, Integer> counts = new HashMap<>();
for (int num : nums) {
if (counts.containsKey(num)) {
counts.replace(num, counts.get(num) + 1);
} else {
counts.put(num, 1);
}
} Map.Entry<Integer, Integer> majorityEntry = null;
for (Map.Entry<Integer, Integer> entry : counts.entrySet()) {
if (majorityEntry == null || entry.getValue() > majorityEntry.getValue()) {
majorityEntry = entry;
}
} return majorityEntry.getKey();
}
}

Python 实现

class Solution:
def majorityElement(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
counts = dict()
for num in nums:
counts[num] = counts.get(num, 0) + 1
return max(counts, key=counts.get)

复杂度分析

  • 时间复杂度:\(O(n)\),其中 \(n\) 为数组的长度。由于哈希表中元素的数目最多为 \(n - \left( \left \lfloor n/2 \right \rfloor + 1 \right) + 1 = n - \left \lfloor n/2 \right \rfloor\),因此遍历一次哈希表最多需要 \(n - \left \lfloor n/2 \right \rfloor\) 次操作,而遍历一遍数组需要 \(n\) 次操作,所以总的时间复杂度是 \(O(n)\) 的
  • 空间复杂度:\(O(n)\),因为哈希表最多需要保存 \(n - \left \lfloor n/2 \right \rfloor\) 个元素

解法三:排序

将数组按照顺序(递增或者递减)排列好后,索引为 \(\left \lfloor n/2 \right \rfloor\) 的元素就是数组的众数。

Java 实现

class Solution {
public int majorityElement(int[] nums) {
Arrays.sort(nums);
return nums[nums.length / 2];
}
}

Python 实现

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

复杂度分析

  • 时间复杂度:\(O(n \log(n))\),其中 \(n\) 表示数组的长度,对数组进行排序的时间复杂度为 \(O(n \log(n))\) 的
  • 空间复杂度:\(O(n)\) 或者 \(O(1)\),取决于是否可以直接对原数组直接进行排序,如果不允许的话,需要额外的空间复制数组

解法四:随机选择【待完成】

思路

Java实现

Python 实现

复杂度分析

解法五:分而治之(Divide and conquer)【待完成】

思路

Java 实现

Python 实现

复杂度分析

解法六:多数投票算法(Boyer-Moore majority vote algorithm)

思路

多数投票算法一般用于寻找一个序列的多数元素(只需要线性时间和常数空间),是一种典型的流式算法(streaming algorithm)。但是,一般来说,该算法无法找到一个序列的众数(mode),除非众数出现的次数大于 \(\lfloor n/2 \rfloor\) 次。多数投票算法的思想是这样:统计一个序列中的所有元素,将多数元素记为 \(+1\),其余的元素记为 \(-1\),那么最后的和一定是正的。具体地,该算法会维护两个变量,一个用于记录序列中的元素,记为 m,一个作为计数器,记为 count。遍历数组中的每个元素,如果当前的 count 为 0,则将当前元素保存在 m 中,并设 count 为1;如果 count 不为0,则判断当前元素与 m 是否相等,相等则 count 加一,不等则 count 减一。遍历结束,变量 m 就是我们寻找的多数元素。

Java 实现

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

Python 实现

class Solution:
def majorityElement(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
me, count = 0, 0
for num in nums:
if count == 0:
me, count = num, 1
elif me == num:
count += 1
else:
count -= 1
return me

复杂度分析

  • 时间复杂度:\(O(n)\),其中 \(n\) 表示数组的长度
  • 空间复杂度:\(O(1)\)

【LeetCode题解】169_求众数(Majority-Element)的更多相关文章

  1. [Swift]LeetCode169. 求众数 | Majority Element

    Given an array of size n, find the majority element. The majority element is the element that appear ...

  2. 【leetcode刷题笔记】Majority Element

    Given an array of size n, find the majority element. The majority element is the element that appear ...

  3. leetCode题解之求二叉树每层的平均值

    1.题目描述 Given a non-empty binary tree, return the average value of the nodes on each level in the for ...

  4. leetCode题解之求二叉树最大深度

    1.题目描述 Given a binary tree, find its maximum depth. The maximum depth is the number of nodes along t ...

  5. Leetcode题目169.求众数(简单)

    题目描述: 给定一个大小为 n 的数组,找到其中的众数.众数是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素. 你可以假设数组是非空的,并且给定的数组总是存在众数. 示例 1: 输入: [3,2,3] ...

  6. Leetcode题解 - 双指针求n数之和

    1. 两数之和 """ 双指针,题目需要返回下标,所以记录一个数字对应的下标 """ class Solution: def twoSum( ...

  7. [LeetCode] Majority Element II 求众数之二

    Given an integer array of size n, find all elements that appear more than ⌊ n/3 ⌋ times. The algorit ...

  8. Leetcode之分治法专题-169. 求众数(Majority Element)

    Leetcode之分治法专题-169. 求众数(Majority Element) 给定一个大小为 n 的数组,找到其中的众数.众数是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素. 你可以假设数组是 ...

  9. [LeetCode] Majority Element 求众数

    Given an array of size n, find the majority element. The majority element is the element that appear ...

随机推荐

  1. 【Win10】一些零碎不好归档的小总结(原谅我这个该死的标题吧)

    一.同步方式获取设备的屏幕分辨率 public static class ScreenResolution { /// <summary> /// 获取屏幕高度. /// </sum ...

  2. 微软研发流程(ALM)管理培训会议(比亚迪汽车)

    主要讨论和演示整体研发流程,包括需求管理.项目计划.开发管理.生成和发布.测试管理等. Figure 1 - 客户现场培训 Figure 2 - 客户现场培训 Figure 3 - 客户现场培训

  3. jquery chosen 插件多选初始化

    <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <m ...

  4. C# 使用ftp下载一个文件夹下的所有文件,包括子目录文件夹

    这篇博客给大家补充一个方法,就是得到一个目录下的所有文件名称.在前端调用,大家写一个递归去遍历就可以了,我在这里就不在写了.具体ftp下载的方法在我的另一篇博客里有,需要的可以去看一下. /// &l ...

  5. hdu A Magic Lamp

    http://acm.hdu.edu.cn/showproblem.php?pid=3183 A Magic Lamp Time Limit: 2000/1000 MS (Java/Others)   ...

  6. reids 安装

    第一步:在VMware中安装CentOS(参考Linux教程中的安装虚拟机) 第二步:在Linux下安装gcc环境 [root@hadoop ~]#yum install gcc-c++ 第三步:将下 ...

  7. C# VS .NET 版本对应关系

    ╔══════╦══════╦═══════╦════ ══╦═══════╗ ║ C# version ║ VS version ║ .NET version ║ CLR version ║ Rel ...

  8. C#MVC和cropper.js实现剪裁图片ajax上传的弹出层

     首先使用cropper.js插件,能够将剪裁后的图片返回为base64编码,后台根据base64编码解析保存图片. jQuery.cropper: 是一款使用简单且功能强大的图片剪裁jquery插件 ...

  9. 【Selenium专题】元素定位之一简单定位

    UI自动化工具千变万化.架构千变万化,但都逃离不开的关键一步就是元素定位.下面以Selenium为例介绍常见的几个元素定位方法 ID -元素id属性 WebElement El = driver.fi ...

  10. log4j学习(二)不同类的日志输出到不同的文件

    目的:一个应用中有两个不同作用的后台服务,我们需要把他们的日志分开,存放到2个不同的日志文件中. 办法:需要在log4j.properties文件中配置两个不同的logger和对应的appender ...