作者: 负雪明烛
id: fuxuemingzhu
个人博客: http://fuxuemingzhu.cn/


题目地址:https://leetcode.com/problems/majority-element/

Total Accepted: 110538 Total Submissions: 268289 Difficulty: Easy

题目描述

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.

题目大意

找出数组中出现次数超过一半的数字。

解题方法

思路

第一想法,用HashMap。嗯。之前也这么做过,但是一想就不对,肯定效率太差。

然后也没想到太好的方法。但是官方给了几个思路:

  1. 时间复杂度: O(n2) — 蛮力法: 依次检查每一个元素是否为众数

  2. 时间复杂度: O(n), 空间复杂度: O(n) — 哈希表: 维护一个每一个元素出现次数的哈希表, 然后找到出现次数最多的元素

  3. 时间复杂度: O(n log n) — 排序: 在排序后找出连续重复出现次数最多的元素

  4. 平均时间复杂度: O(n), 最坏复杂度: 无穷大 — 随机算法: 随机选取一个元素计算其是否为众数. 如果不是,就重复上一步骤直到找到为止。 由于选出众数的概率 1 / 2, 因此期望的尝试次数 < 2

  5. 时间复杂度: O(n log n) — 分治法: 将数组拆成2半, 然后找出前一半的众数A和后一半的众数B。则全局众数要么是A要么是B。如果 A == B, 则它自然而然就是全局众数。 如果不是, 则A和B都是候选众数, 则至多只需要检查这两个元素的出现次数即可。

  6. 时间复杂度, T(n) = T(n/2) + 2n = O(n log n).

  7. 时间复杂度: O(n) — Moore投票算法: 我们维护一个当前的候选众数和一个初始为0的计数器。遍历数组时,我们看当前的元素x:
    - 如果计数器是0, 我们将候选众数置为 x 并将计数器置为 1 如果计数器非0, 我们根据x与当前的候选众数是否相等对计数器+1或者-1;
    - 一趟之后, 当前的候选众数就是所求众数.

  8. 时间复杂度 = O(n). 时间复杂度: O(n) — 位操作法: 我们需要32次迭代,
    - 每一次计算所有n个数的第i位的1的个数。由于众数一定存在,那么或者1的个数 0的个数多 或者反过来(但绝不会相同)。
    - 众数的第i位一定是计数较多数字。

hashmap统计次数

加入不考虑空间复杂度,直接使用字典统计次数,然后找出出现次数最大的那个数字,就能通过。

python代码如下:

class Solution(object):
def majorityElement(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
count = collections.Counter(nums)
return count.most_common(1)[0][0]

C++代码如下:

class Solution {
public:
int majorityElement(vector<int>& nums) {
const int N = nums.size();
unordered_map<int, int> count;
for (int n : nums)
++count[n];
for (auto& c : count) {
if (c.second > N / 2) {
return c.first;
}
}
return -1;
}
};

摩尔投票法 Moore Voting

这个投票方法挺好玩。就是多数派问题。

这个思路是这样的:

  1. 对于vi,如果c此时为未知状态,则c=v[i],t=1,递增i。
  2. 如果c==v[i],++t,递增i。
  3. 如果c!=v[i],–t,如果t==0,将c置为未知状态,递增i。
  4. 所有投票处理完毕后,如果c为未知状态,则说明不存在任何候选人的得票数过半,否则重新遍历数组v,统计候选人c的实际得票总数,如果c的得票数确实过半,则c就是最终结果。

这个做法的原理就是既然有出现次数超过一半的数字,那么我们把没出现一半的数字的次数进行抵消,出现一半以上的数字仍然不会被完全消除掉。

比如对于数据[1,2,1,1,3,1,4,4]

i		1	2	3	4	5	6	7	8
v[i] 1 2 1 1 3 1 4 4
c 1 ? 1 1 1 1 1 ?
t 1 0 1 2 1 2 1 0

程序运行的最终结果,c处于未知状态,说明对于投票数组v,不存在任何候选人的得票数过半。

如果v[1…9]={1,2,1,1,3,1,4,4,1},此时c的最后状态为1,重新遍历数组v,查看候选人1的得票数是否确实过半,统计结果1出现了5次,大于9/2,所以候选人1的票数过半。

因为题目中已经保证了存在数据出现过半。所以结尾的c那个元素一定不是不确定状态,直接返回就好。

C++代码如下:

class Solution {
public:
int majorityElement(vector<int>& nums) {
int c = -1;
int t = 0;
for (int n : nums) {
if (t == 0) {
c = n;
t = 1;
} else {
if (n == c) {
++t;
} else {
--t;
}
}
}
return c;
}
};

python版本代码如下:

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

Java代码:

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

位运算统计位数

位操作法: 我们需要32次迭代, 每一次计算所有n个数的第i位的1的个数。

由于众数一定存在,那么或者1的个数0的个数多,或者反过来(但绝不会相同)。

众数的第i位一定是计数较多数字(1或0)。

这个题需要注意的是如何设置一个int的指定位是1:或上一个该指定为是1其余位是0的数字即可。

时间复杂度 = O(n).

一、指定的某一位数置1

宏 #define setbit(x,y)  x|=(1<<y)

二、指定的某一位数置0

宏  #define clrbit(x,y)  x&=~(1<<y)

三、指定的某一位数取反

宏  #define reversebit(x,y)  x^=(1<<y)

三、获取的某一位的值

宏 #define getbit(x,y)   ((x) >> (y)&1)

C++代码如下:

class Solution {
public:
int majorityElement(vector<int>& nums) {
const int N = nums.size();
int res = 0;
for (int i = 0; i < 32; ++i) {
int mask = 1 << i;
int onecount = 0;
for (int n : nums) {
if (n & mask) {
++onecount;
}
}
if (onecount > N / 2)
res |= mask;
}
return res;
}
};

相似题目

229. Majority Element II

参考资料

多数派问题
https://blog.csdn.net/qq_37858386/article/details/78419911

日期

2016/5/1 0:00:49
2018 年 10 月 29 日 —— 美好的一周又开始了
2018 年 11 月 11 日 —— 剁手节快乐

【LeetCode】169. Majority Element 解题报告(Java & Python & C+)的更多相关文章

  1. LeetCode 169 Majority Element 解题报告

    题目要求 Given an array of size n, find the majority element. The majority element is the element that a ...

  2. LeetCode 169. Majority Element解题方法

    题目: Given an array of size n, find the majority element. The majority element is the element that ap ...

  3. 【LeetCode】162. Find Peak Element 解题报告(Python)

    [LeetCode]162. Find Peak Element 解题报告(Python) 标签(空格分隔): LeetCode 题目地址:https://leetcode.com/problems/ ...

  4. 【LeetCode】120. Triangle 解题报告(Python)

    [LeetCode]120. Triangle 解题报告(Python) 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 题目地址htt ...

  5. [LeetCode] 169. Majority Element 多数元素

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

  6. leetcode 169. Majority Element 、229. Majority Element II

    169. Majority Element 求超过数组个数一半的数 可以使用hash解决,时间复杂度为O(n),但空间复杂度也为O(n) class Solution { public: int ma ...

  7. Leetcode#169. Majority Element(求众数)

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

  8. 23. leetcode 169. Majority Element

    169. Majority Element Given an array of size n, find the majority element. The majority element is t ...

  9. Java for LeetCode 169 Majority Element

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

随机推荐

  1. 为什么Mysql用B+树做索引而不用B-树或红黑树

    B+树做索引而不用B-树 那么Mysql如何衡量查询效率呢?– 磁盘IO次数. 一般来说索引非常大,尤其是关系性数据库这种数据量大的索引能达到亿级别,所以为了减少内存的占用,索引也会被存储在磁盘上. ...

  2. GWAS在农业上应用

    农业的组学技术应用虽然落后于人的研究,这是什么意义的问题,但有时农业基因组有自己无可比拟的优势,那就是材料.下面介绍GWAS应用. GWAS(Genome-wide association study ...

  3. 【蛋白质基因组】Proteogenomics方法介绍及分析思路

    概念 利用蛋白质组学数据,结合基因组数据(DNA).转录组数据(RNA)来研究基因组注释问题,被称为蛋白质基因组学."蛋白质基因组学"一词由Jaffe 等于2004 年首次提出,作 ...

  4. Hi3516开发笔记(六):通过HiTools使用USB/串口将uboot、kernel、roofts和userdata按照分区表烧写镜像

    若该文为原创文章,转载请注明原文出处本文章博客地址:https://hpzwl.blog.csdn.net/article/details/121706033红胖子(红模仿)的博文大全:开发技术集合( ...

  5. ysoserial-CommonsBeanutils1的shiro无依赖链改造

    ysoserial-CommonsBeanutils1的shiro无依赖链改造 一.CB1利用链分析 此条利用链需要配合Commons-Beanutils组件来进行利用,在shiro中是自带此组件的. ...

  6. 【vector的输出问题】 洛谷 P1996 约瑟夫问题

    题目:P1996 约瑟夫问题 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 可恶啊,本来是一道不算难的题,硬是因为cin,cout同步流卡了我一天qwq 关闭cin,cout同步流 ...

  7. HDFS初探之旅(二)

    6.HDFS API详解 Hadoop中关于文件操作类疾病上全部在"org.apache.hadoop.fs"包中,这些API能够支持的操作包含:打开文件.读写文件.删除文件等. ...

  8. JDBC(3):PreparedStatement对象介绍

    一,PreparedStatement介绍 PreperedStatement是Statement的子类,它的实例对象可以通过Connection.preparedStatement()方法获得,相对 ...

  9. linux shell学习之shell流程控制

    在linux shell编程中,流程控制结构与语句,也算是shell脚本中的重点了,不了解的朋友,跟随脚本小编一起来学习下吧. linux控制流结构学习. 一,shell控制流结构 1.控制结构   ...

  10. 使用RabbitMQ搭建MQTT服务

    由于近期公司需要搭建一套物联网采集环境,底层设备采用MQTT协议传输数据.服务器环境为linux,考虑到现有环境已经有RabbitMQ环境,Rabbit是基于AMQP协议开发的一套高效的消息传输队列. ...