作者: 负雪明烛
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. 【豆科基因组】鹰嘴豆Chickpea (Cicer arietinum L.)429个自然群体重测序2019NG

    目录 一.来源 二.结果 材料测序.变异检测.群体结构和LD衰减 驯化后经历选择的候选基因组区域 起源中心.迁移路线和多样性 GWAS 一.来源 Resequencing of 429 chickpe ...

  2. Augustus 进行基因注释

      目前的从头预测软件大多是基于HMM(隐马尔科夫链)和贝叶斯理论,通过已有物种的注释信息对软件进行训练,从训练结果中去推断一段基因序列中可能的结构,在这方面做的最好的工具是AUGUSTUS它可以仅使 ...

  3. cmd查看同一个局域网内电脑IP

    win+R,cmd  #快速打开cmd窗口 net view  #查看本地局域网内开启了哪些计算机共享  运行后可以看到已共享的计算机名称 net view ip  #查看对方局域网内开启了哪些共享 ...

  4. 强化学习实战 | 自定义Gym环境之井字棋

    在文章 强化学习实战 | 自定义Gym环境 中 ,我们了解了一个简单的环境应该如何定义,并使用 print 简单地呈现了环境.在本文中,我们将学习自定义一个稍微复杂一点的环境--井字棋.回想一下井字棋 ...

  5. C语言中的各种字符串输入方法

    C语言从stdin读取一行字符串的几种方法 gets gets函数的头文件是<stdio.h>,原型如下: char *gets(char *s); gets从stdin中读入一行内容到s ...

  6. 生产调优4 HDFS-集群扩容及缩容(含服务器间数据均衡)

    目录 HDFS-集群扩容及缩容 添加白名单 配置白名单的步骤 二次配置白名单 增加新服务器 需求 环境准备 服役新节点具体步骤 问题1 服务器间数据均衡 问题2 105是怎么关联到集群的 服务器间数据 ...

  7. A Child's History of England.22

    CHAPTER 8 ENGLAND UNDER WILLIAM THE FIRST, THE NORMAN CONQUEROR Upon the ground where the brave Haro ...

  8. acid, acknowledge, acquaint

    acid sulphuric|hydrochloric|nitric|carbolic|citric|lactic|nucleic|amino acid: 硫|盐|硝|碳|柠檬|乳|核|氨基酸 王水是 ...

  9. 在调用系统相册时,UIIMagePickerController使用中偷换StatusBar颜色的问题

    在调用系统相册时,UIIMagePickerController使用中偷换StatusBar颜色的问题 此时解决办法是 #pragma mark - UIImagePickerController D ...

  10. 【Linux】【Services】【Package】yum

    Linux程序包管理(2)       CentOS: yum, dnf       URL: ftp://172.16.0.1/pub/        YUM: yellow dog, Yellow ...