当前位置: 首页 > news >正文

leetcode——169.多数元素(多解法)

169. 多数元素

题目描述

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

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

示例 1:
输入:nums = [3,2,3]
输出:3

示例 2:
输入:nums = [2,2,1,1,1,2,2]
输出:2

提示:
n == nums.length
1 <= n <= 5 * 10^4
-10^9 <= nums[i] <= 10^9

进阶:尝试设计时间复杂度为 O(n)、空间复杂度为 O(1) 的算法解决此问题。

哈希表解法

使用哈希表来记录数组中元素出现的次数。

哈希表的基本用法

首先,我们需要了解一下哈希表的基本用法。

import java.util.HashMap;
import java.util.Map;public class HashTableDemo {public static void main(String[] args) {// 创建一个哈希表Map<String, Integer> map = new HashMap<>();// 添加一个键值对map.put("apple", 1);System.out.println("HashMap: " + map); //正确输出: HashMap: {apple=1}// 检查一下这个键是否在哈希表中boolean exists = map.containsKey("apple");System.out.println("Contains 'apple' key: " + exists); //正确输出: Contains 'apple' key: true// 获取这个键对应的值Integer value = map.get("apple");System.out.println("Value for 'apple': " + value); //正确输出: Value for 'apple': 1// 在哈希表中删掉这个键map.remove("apple");System.out.println("HashMap after remove: " + map); //正确输出: HashMap after remove: {}// 添加一些键值对map.put("banana", 2);map.put("cherry", 3);System.out.println("HashMap: " + map); //正确输出: HashMap: {banana=2, cherry=3}// 输出哈希表中的键值对for(Map.Entry<String, Integer> entry : map.entrySet()) {System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());}//正确输出: Key = banana, Value = 2//                 Key = cherry, Value = 3// 输出哈希表的键值对个数int size = map.size();System.out.println("Size of HashMap: " + size); //正确输出: Size of HashMap: 2}
}

用到的方法:
创建

Map<,> map = new Hash<>();

检查是否包含

boolean con = map.containsKey(key);

插入更新键值对

map.put(key, value);

哈希解法代码

class Solution {private Map<Integer, Integer> count(int[] nums) {Map<Integer, Integer> map = new HashMap<Integer, Integer>();for(int i = 0; i < nums.length; i++) {// 如果哈希表中未包含这个数字if(! map.containsKey(nums[i])) {// 则添加这个数字,对应的次数为1map.put(nums[i], 1);} else {// 否则更新这个数字的次数加一map.put(nums[i], map.get(nums[i]) + 1);}}return map;}public int majorityElement(int[] nums) {Map<Integer, Integer> map = count(nums);for(Integer key : map.keySet()) {// 遍历哈希表,若次数大于n/2,就返回对应的数字if(map.get(key) > nums.length/2) return key;}// 找不到多数元素返回0return 0;}
}

排序

思路

排序解法的难点在于理解算法思路,而不是代码过程。
因为题目说多数元素的个数必大于n/2
那么将代码升序(或降序)排序之后,多数元素必定会在数组的中间点。

可以这样想象,如果你把数组按照升序或者降序排列,那么多数元素由于数量超过半数,就一定会占据数组中间的位置。无论它在前半部分的数量还是在后半部分的数量,由于它的数量超过了总数的一半,因此它肯定会延伸到数组的中间,也就是中位数的位置。
比如考虑一个由 7 个元素组成的数组 [2, 2, 2, 2, 5, 5, 5],其中出现最多的元素就是 2,数量为 4 > 7/2,排序后得到的数组是 [2, 2, 2, 2, 5, 5, 5],你可以看到元素 “2” 在数组的中间。
这就是为什么在排序后,多数元素会出现在数组的中间。因此,只需要返回排序后数组的中位数就好。在编程实现上,这通常意味着返回索引为 n/2 的元素(在 Java 中,数组的索引从 0 开始)。

代码

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

这里面用到了Arrays类的一个方法,即排序方法Arrays.sort(),参数是数组,默认升序排序。

分治法

思路

分治法的过程 : 先分解,后合并。
也就是将数组分成两半,两个子问题来处理,然后再将两个子问题得到的结果合并,得到大问题的答案。

对应在这个问题当中,可以得到
大问题:求整个数组的多数元素
子问题:将数组进行划分,左右两个子数组的多数元素
然后再依次进行划分直到子数组的长度为一时,则唯一的元素就是它的多数元素,进行返回,也就是递归条件

代码

基于这里,可以得到我们的递归函数中划分部分代码

private int Rec(int[] nums, int start, int end) {// 当数组只有一个元素时,结束递归if(start == end) return nums[start];// 算出中间点,进行划分int mid = (start + end) /2;// 得到左子数组的多数元素int left = Rec(nums, start, mid);// 得到右子数组的多数元素int right = Rec(nums, mid, end);// 合并过程}

加上合并即全部代码:

class Solution {// 计算子数组中多数元素出现的个数private int count(int[] nums, int start, int end, int num){int count = 0;for(int i = start; i <= end; i++) {if(nums[i] == num) count++;}return count;}private int Rec(int[] nums, int start, int end) {// 当数组只有一个元素时,结束递归if(start == end) return nums[start];// 算出中间点,进行划分int mid = (start + end) /2;// int mid = (end - start) / 2 + start;// 得到左子数组的多数元素int left = Rec(nums, start, mid);// 得到右子数组的多数元素// 注意这里起点时mid+1int right = Rec(nums, mid+1, end);// 合并过程// 若左右子数组的多数元素相同,则直接返回if(left == right) return left;// 否则算出左右多数元素在整个数组出现的次数,次数多的则是大数组的多数元素int leftcount = count(nums, start, end, left);int rightcount = count(nums, start, end, right);// if(leftcount > rightcount) return left;// else return right;return leftcount > rightcount ? left : right;}public int majorityElement(int[] nums) {return Rec(nums, 0, nums.length-1);}
}

相关文章:

  • 回溯算法05(leetcode491/46/47)
  • 消防体验馆升级,互动媒体点亮安全之路!
  • MySQL--复合查询
  • wordpress woocommer 添加代码实现,点击按钮,将产品添加到购物车并且跳转到结账页面
  • 西储大学数据集学习
  • 2024年华为OD机试真题-火星文计算-C++-OD统一考试(C卷D卷)
  • Linux 删除SSH密钥(id_ed25519),重新生成
  • 生成式AI模型大PK——GPT-4、Claude 2.1和Claude 3.0 Opus
  • WPF之TextBlock文本标签
  • nuxt3+Element Plus项目搭建过程记录
  • 【源码】Spring Data JPA原理解析之Repository执行过程及SimpleJpaRepository源码
  • K-独立钻石(dfs),G-邪恶铭刻(贪心)
  • 反编译 Trino Dockerfile
  • 基于单片机的自行车里程监测系统的设计
  • 撤销最近一次的提交,使用git revert 和 git reset的区别
  • 【108天】Java——《Head First Java》笔记(第1-4章)
  • 【跃迁之路】【477天】刻意练习系列236(2018.05.28)
  • 【知识碎片】第三方登录弹窗效果
  • flask接收请求并推入栈
  • github指令
  • gulp 教程
  • Laravel 实践之路: 数据库迁移与数据填充
  • PyCharm搭建GO开发环境(GO语言学习第1课)
  • React16时代,该用什么姿势写 React ?
  • 从0搭建SpringBoot的HelloWorld -- Java版本
  • 从伪并行的 Python 多线程说起
  • 分布式事物理论与实践
  • 复杂数据处理
  • 力扣(LeetCode)22
  • 前端每日实战:61# 视频演示如何用纯 CSS 创作一只咖啡壶
  • 前端面试之CSS3新特性
  • 前端自动化解决方案
  • 深度学习中的信息论知识详解
  • 微服务框架lagom
  • 协程
  • 学习笔记:对象,原型和继承(1)
  • 延迟脚本的方式
  • ###C语言程序设计-----C语言学习(6)#
  • $(function(){})与(function($){....})(jQuery)的区别
  • (01)ORB-SLAM2源码无死角解析-(56) 闭环线程→计算Sim3:理论推导(1)求解s,t
  • (BFS)hdoj2377-Bus Pass
  • (Matalb回归预测)PSO-BP粒子群算法优化BP神经网络的多维回归预测
  • (附源码)ssm基于jsp高校选课系统 毕业设计 291627
  • (力扣记录)235. 二叉搜索树的最近公共祖先
  • (十)Flink Table API 和 SQL 基本概念
  • (一)80c52学习之旅-起始篇
  • (一)搭建springboot+vue前后端分离项目--前端vue搭建
  • (一)基于IDEA的JAVA基础1
  • (转)http协议
  • (自适应手机端)响应式服装服饰外贸企业网站模板
  • *上位机的定义
  • ..回顾17,展望18
  • .CSS-hover 的解释
  • .Net Core与存储过程(一)
  • .NET Framework 的 bug?try-catch-when 中如果 when 语句抛出异常,程序将彻底崩溃