题目

剑指 Offer 39. 数组中出现次数超过一半的数字

思路1(排序)

  • 因为题目说一定会存在超过数组长度一半的一个数字,所以我们将数组排序后,位于length/2位置的一定是众数

代码

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

复杂度分析

  • 时间复杂度:\(O(NlogN)\)
  • 空间复杂度:\(O(1)\)

思路2(哈希表)

  • 遍历一遍数组,将数组的值作为键,出现的次数作为值,存放到哈希表中
  • 遍历哈希表,找到出现次数最多的那一个键值对就是我们要的众数

代码

class Solution {
public int majorityElement(int[] nums) {
HashMap<Integer, Integer> map = new HashMap<>();
for (int n : nums) {
map.put(n, map.getOrDefault(n, 0) + 1);
} int max = 0;
int res = 0;
for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
if (max < entry.getValue()) {
max = entry.getValue();
res = entry.getKey();
}
}
return res;
}
}

复杂度分析

  • 时间复杂度:\(O(N)\)
  • 空间复杂度:\(O(N)\)

思路3(分治)

  • 将数组从中间开始不断分成两份,直到只剩下一个元素时候开始返回
  • 如果left和right出现的频率一样,直接返回
  • 计算left和right在lo~hi范围内出现的频率,将高频率的返回
  • 为什么可以用这个方法?比如有[1, 2, 3, 2, 2, 2, 5, 4, 2],共有9个元素,共会被分成5份(每份一个或者两个元素),然后从每份中再获取一个值,共获取5个值,又因为众数的个数要大于数组的长度,所以,众数一定会至少被选中一个,只要被选中一个,那么我们的countInRange函数会根据范围帮我们计算出最多出现的元素个数即众数

代码

class Solution {
public int majorityElement(int[] nums) {
return majorityElementRec(nums, 0, nums.length-1);
} public int majorityElementRec(int[] nums, int lo, int hi) {
// 如果只有一个元素,那么直接返回
if (lo == hi) {
return nums[lo];
} // 获取中间值
int mid = lo + (hi - lo) / 2;
// 递归左边和右边,直到剩下一个元素
int left = majorityElementRec(nums, lo, mid);
int right = majorityElementRec(nums, mid+1, hi); // 相等只需要返回一个
if (left == right) {
return left;
} // 计算left和right在lo~hi范围中的出现的次数
int leftCount = countInRange(nums, left, lo, hi);
int rightCount = countInRange(nums, right, lo, hi); // 返回出现次数多的数
return leftCount > rightCount ? left : right;
} // 统计目标数字在指定范围出现的次数
public int countInRange(int[] nums, int target, int lo, int hi) {
int count = 0;
for (int i = lo; i <= hi; i++) {
if (nums[i] == target) {
count++;
}
}
return count;
}
}

复杂度分析

  • 时间复杂度:\(O(NlogN)\)
  • 空间复杂度:\(O(logN)\),递归过程中使用了额外的栈空间

思路4(摩尔投票法)

  • 众数记为+1,把其他数记为-1,将它们全部加起来,和最终会大于0
  • 假设众数记为res,票数记为votes,假设有这么一个数组:[1, 2, 3, 2, 2, 2, 5, 4, 2],使用摩尔投票法的过程如下:
    • i=0时:因为当前票数为0,所以将1赋值给res,同时票数也加一。此时res=1 votes=1
    • i=1时:2不等于1,所以票数要减1,此时res=1 votes=0
    • i=2时:因为票数为0,所以众数res要指向当前的3,然后票数加一,此时res=3 votes=1
    • i=3时:2不等于3,所以票数要减1,此时res=3 votes=0
    • i=4时:因为票数为0,所以众数res要指向当前的2,然后票数加一,此时res=2 votes=1
    • i=5时:由于2=2,所以票数加一,此时res=2 votes=2
    • i=6时:5不等于2,所以票数要减1,此时res=2 votes=1
    • i=7时:4不等于2,所以票数要减1,此时res=2 votes=0
    • i=8时:因为票数为0,所以众数res要指向当前的2,然后票数加一,此时res=2 votes=1
    • 最后就直接输出res即为众数

代码

class Solution {
public int majorityElement(int[] nums) {
// 代表结果的众数
int res = nums[0];
// 统计票数
int votes = 0; for (int i = 0; i < nums.length; i++) {
// 刚开始是0票,所以把数组的第一个元素作为众数
// 如果以后的循环votes票数被抵消掉了为0,那么下一个元素就作为众数
if (votes == 0) {
res = nums[i];
}
// 和当前众数相同的,那么票数就加1
if (res == nums[i]) {
votes++;
} else {
// 如果和当前票数不同,票数就被抵消掉了一个
votes--;
}
} return res;
}
}

复杂度分析

  • 时间复杂度:\(O(N)\)
  • 空间复杂度:\(O(1)\)

力扣 - 剑指 Offer 39. 数组中出现次数超过一半的数字的更多相关文章

  1. 剑指 Offer 39. 数组中出现次数超过一半的数字

    剑指 Offer 39. 数组中出现次数超过一半的数字 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字. 你可以假设数组是非空的,并且给定的数组总是存在多数元素. 示例 1: 输入: [ ...

  2. 剑指 Offer 39. 数组中出现次数超过一半的数字 + 摩尔投票法

    剑指 Offer 39. 数组中出现次数超过一半的数字 Offer_39 题目描述 方法一:使用map存储数字出现的次数 public class Offer_39 { public int majo ...

  3. 【Java】 剑指offer(39) 数组中出现次数超过一半的数字

    本文参考自<剑指offer>一书,代码采用Java语言. 更多:<剑指Offer>Java实现合集   题目 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字.例如 ...

  4. 每日一题 - 剑指 Offer 39. 数组中出现次数超过一半的数字

    题目信息 时间: 2019-06-29 题目链接:Leetcode tag: 数组 哈希表 难易程度:简单 题目描述: 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字. 假设数组是非空的 ...

  5. 剑指Offer:数组中出现次数超过一半的数字【39】

    剑指Offer:数组中出现次数超过一半的数字[39] 题目描述 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字.例如,输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}.由于这 ...

  6. 【剑指Offer】数组中出现次数超过一半的数字 解题报告(Python)

    [剑指Offer]数组中出现次数超过一半的数字 解题报告(Python) 标签(空格分隔): 剑指Offer 题目地址:https://www.nowcoder.com/ta/coding-inter ...

  7. Go语言实现:【剑指offer】数组中出现次数超过一半的数字

    该题目来源于牛客网<剑指offer>专题. 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字.例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}.由于数字2在数组 ...

  8. 剑指OFFER之数组中出现次数超过一半的数字(九度OJ1370)

    题目描述: 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字.例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}.由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2 ...

  9. 剑指Offer 28. 数组中出现次数超过一半的数字 (数组)

    题目描述 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字.例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}.由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2. ...

随机推荐

  1. ReScript 与 TypeScript,谁是前端圈的“当红辣子鸡”

    摘要: ReScript 和 TypeScript 的出现都是为了更好地使用JavaScript,但两者还是有很大的不同. 本文分享自华为云社区<[云创共驻]ReScript 和 TypeScr ...

  2. SpringBoot - 搭建静态资源存储服务器

    目录 前言 环境 实现效果 具体实现 文件上传 配置类 上传接口 上传实现 辅助类 实体 上传测试 文件访问 配置类 项目源码 前言 记录下SpringBoot下静态资源存储服务器的搭建. 环境 wi ...

  3. 集合Collection ----List集合

    Collection集合体系的特点: set系列集合:添加的元素是 无序,不重复,无索引的 ----HashSet: 无序,不重复,无索引 ----LinkedHashSet: 有序,不重复,无索引 ...

  4. 使用metaweblog API实现通用博客发布 之 版本控制

    使用metaweblog API实现通用博客发布 之 版本控制 接上一篇本地图片自动上传以及替换路径,继续解决使用API发布博客的版本控制问题. 当本地文档修订更新以后,如何发现版本更新,并自动发布到 ...

  5. 怎样在Linux中查看apache是用那个httpd.conf

    第一步:找到apache启动命令: [root@WAPBJ01 ~]# ps -ef|grep httpdroot     10575     1  0 19:45 ?        00:00:03 ...

  6. Java集合框架总览

    Java集合 Java 集合框架主要包括两种类型的容器,一种是集合(Collection),存储一个元素集合,另一种是图(Map),存储键/值对映射.Collection 接口有 3 种子类型,Lis ...

  7. 启动jemeter 报错相关解决方案

    1:当启动jemeter时报错"页面文件太小,无法完成操作" 如图: 是说明分配的内容不足,即可调整内存重启即可解决 1):打开:控制面板>系统和安全>系统 2):点击 ...

  8. Kafka与RocketMq文件存储机制对比

    一个商业化消息队列的性能好坏,其文件存储机制设计是衡量一个消息队列服务技术水平和最关键指标之一. 开头问题 kafka文件结构和rocketMQ文件结构是什么样子?特点是什么? 一.目录结构 Kafk ...

  9. YbtOJ#631-次短路径【左偏树,最短路】

    正题 题目链接:https://www.ybtoj.com.cn/contest/114/problem/1 题目大意 给出\(n\)个点\(m\)条边的一张无向图,对于每个点\(i\)求不经过\(i ...

  10. 经典软件测试面试题目:Android 和 ios 测试区别?这样回答:稳!

    Android 和  ios 测试区别? App 测试中 ios 和 Android 有哪些区别呢?1.Android 长按 home 键呼出应用列表和切换应用,然后右滑则终止应用:2.多分辨率测试, ...