剑指offer-28、数组中出现次数超过⼀半的数字

题⽬描述

数组中有⼀个数字出现的次数超过数组⻓度的⼀半,请找出这个数字。例如输⼊⼀个⻓度为 9 的数组 {1,2,3,2,2,2,5,4,2} 。由于数字 2 在数组中出现了 5 次,超过数组⻓度的⼀半,因此输出 2 。如果不存在则输出 0 。

思路及解答

哈希表法(HashMap)

哈希表法通过统计每个数字的出现次数来解决问题。遍历数组时,使用哈希表记录每个数字出现的次数,一旦发现某个数字的出现次数超过数组长度的一半,立即返回该数字。

java 复制代码
public class Solution {
    public int MoreThanHalfNum(int[] nums) {
        // 创建哈希表,key为数字,value为出现次数
        Map<Integer, Integer> map = new HashMap<>();
        for (int num : nums) {
            // 获取当前数字的出现次数并加1,若不存在则初始化为0再加1
            int count = map.getOrDefault(num, 0) + 1;
            // 若当前数字出现次数已超过数组长度一半,则返回该数字
            if (count > nums.length / 2) {
                return num;
            }
            map.put(num, count); // 更新哈希表
        }
        return 0; // 如果不存在多数元素,返回0(但题目假设总是存在)
    }
}
  • 时间复杂度:O(n),其中 n 是数组的长度。我们只需遍历数组一次。
  • 空间复杂度:O(n),最坏情况下需要存储所有不同的数字。

排序法

排序法的思路非常巧妙:​由于多数元素的数量超过数组长度的一半,那么将数组排序后,中间位置的元素一定是多数元素。

java 复制代码
public class Solution {
    public int majorityElement(int[] nums) {
        Arrays.sort(nums); // 对数组进行排序
        return nums[nums.length / 2]; // 返回中间位置的元素
    }
}

摩尔投票法(Boyer-Moore Voting Algorithm)

  1. 如果使⽤ hashmap 直接统计,需要额外的空间,我们不希望使⽤额外空间;
  2. 如果使⽤排序之后再统计,需要时间复杂度为O(nlogn), 我们希望时间复杂度更低⼀点。

摩尔投票法是一种高效且空间复杂度低的算法。其核心思想是通过票数的抵消来找出多数元素 。算法维护一个候选众数 candidate 和其票数 count。遍历数组时,若 count 为0,则选择当前数字作为候选;若当前数字与候选相同,则票数加1,否则减1。由于多数元素的存在,最终剩下的候选一定是多数元素。

java 复制代码
public class Solution {
    public int majorityElement(int[] nums) {
        int candidate = 0; // 候选众数
        int count = 0;     // 票数统计
        
        for (int num : nums) {
            if (count == 0) { // 如果票数为0,选择当前数字作为候选
                candidate = num;
            }
            // 如果当前数字与候选相同,则票数加1,否则减1
            count += (num == candidate) ? 1 : -1;
        }
        
        // 可选:验证candidate是否真的是多数元素(根据题目假设,通常不需要)
        // 但如果题目要求不存在多数元素时返回0,则需要验证步骤
        count = 0;
        for (int num : nums) {
            if (num == candidate) count++;
        }
        
        return count > nums.length / 2 ? candidate : 0;
    }
}
  • 时间复杂度:O(n),只需遍历数组两次(一次投票,一次验证)。
  • 空间复杂度:O(1),只使用了常数个额外变量
相关推荐
木易 士心3 分钟前
Spring AI 核心架构解析:构建企业级 AI 应用的 Java 新范式
java·spring
61900833613 分钟前
linux 安装jdk
java·linux·运维
懂得节能嘛.16 分钟前
【动态配置中心】Java+Redis构建动态配置中心
java·开发语言·redis
专注于大数据技术栈17 分钟前
Java中JDK、JRE、JVM概念
java·开发语言·jvm
YuanlongWang21 分钟前
C# 基础——值类型与引用类型的本质区别
java·jvm·c#
Kay_Liang1 小时前
大语言模型如何精准调用函数—— Function Calling 系统笔记
java·大数据·spring boot·笔记·ai·langchain·tools
自由的疯1 小时前
Java 如何学习Docker
java·后端·架构
自由的疯1 小时前
Java Docker本地部署
java·后端·架构
007php0071 小时前
猿辅导Java面试真实经历与深度总结(二)
java·开发语言·python·计算机网络·面试·职场和发展·golang
摇滚侠1 小时前
Spring Boot 3零基础教程,WEB 开发 内容协商机制 笔记34
java·spring boot·笔记·缓存