算法题 多数元素

LeetCode 169. 多数元素

问题描述

给定一个大小为 n 的数组,找到其中的多数元素。多数元素指在数组中出现次数 大于 ⌊n/2⌋ 的元素。假设数组非空,且总是存在多数元素。

示例

输入: [3,2,3]
输出: 3

输入: [2,2,1,1,1,2,2]
输出: 2

算法思路

方法一:摩尔投票法(最优解)

  1. 核心思想:多数元素与其他元素两两抵消后,剩余元素必为多数元素
  2. 步骤
    • 初始化候选元素 candidate 和计数器 count = 0
    • 遍历数组:
      • count == 0 时,设置当前元素为候选元素
      • 当元素等于候选元素时,count++
      • 否则 count--
  3. 结果:最终候选元素即为多数元素

方法二:排序法

  1. 核心思想:排序后中间位置必为多数元素
  2. 步骤
    • 将数组排序
    • 返回中间位置元素 nums[n/2]

代码实现

方法一:摩尔投票法

class Solution {
    public int majorityElement(int[] nums) {
        int candidate = 0;
        int count = 0;
        
        for (int num : nums) {
            if (count == 0) {
                candidate = num; // 设置新候选
            }
            // 更新计数器
            count += (num == candidate) ? 1 : -1;
        }
        return candidate; // 最终候选即为多数元素
    }
}

方法二:排序法

import java.util.Arrays;

class Solution {
    public int majorityElement(int[] nums) {
        Arrays.sort(nums);
        return nums[nums.length / 2]; // 中间位置必为多数元素
    }
}

算法分析

  • 时间复杂度
    • 摩尔投票法:O(n)(单次遍历)
    • 排序法:O(n log n)(排序时间复杂度)
  • 空间复杂度
    • 摩尔投票法:O(1)(常数空间)
    • 排序法:O(1)O(n)(取决于排序算法)

算法过程

输入 nums = [2,2,1,1,1,2,2]

步骤  元素  候选(candidate)  计数器(count)
1     2      2 (初始化)       1
2     2      2               2
3     1      2               1
4     1      2               0  → 重置候选
5     1      1 (新候选)       1
6     2      1               0  → 重置候选
7     2      2 (新候选)       1
结果:candidate = 2

测试用例

public static void main(String[] args) {
    Solution solution = new Solution();
    
    // 测试用例1:标准示例
    int[] nums1 = {3,2,3};
    System.out.println("Test 1: " + solution.majorityElement(nums1)); // 3
    
    // 测试用例2:多数元素在末尾
    int[] nums2 = {2,2,1,1,1,2,2};
    System.out.println("Test 2: " + solution.majorityElement(nums2)); // 2
    
    // 测试用例3:单一元素
    int[] nums3 = {5};
    System.out.println("Test 3: " + solution.majorityElement(nums3)); // 5
    
    // 测试用例4:多数元素连续出现
    int[] nums4 = {1,1,1,2,3};
    System.out.println("Test 4: " + solution.majorityElement(nums4)); // 1
    
    // 测试用例5:多数元素交替出现
    int[] nums5 = {4,5,4,5,4}; 
    System.out.println("Test 5: " + solution.majorityElement(nums5)); // 4
}

关键点

  1. 摩尔投票法原理

    • 多数元素数量 > n/2
    • 每次抵消操作相当于移除两个不同元素
    • 最终剩余元素必为多数元素
  2. 重置候选条件

    • 当计数器归零时,表示之前的所有元素已完成抵消
    • 此时从当前位置开始新一轮统计
  3. 算法正确性保证

    • 题目假设数组非空且存在多数元素
    • 无需验证最终结果的正确性

常见问题

1. 为什么摩尔投票法不验证结果?
题目明确说明数组中总是存在多数元素,因此最终候选元素必定正确。

2. 处理不存在多数元素的情况?
若题目不保证存在多数元素,需增加验证步骤:

int verify = 0;
for (int num : nums) {
    if (num == candidate) verify++;
}
return (verify > nums.length/2) ? candidate : -1;

3. 为什么排序法返回中间元素?
多数元素数量超过一半,排序后中间位置(n/2)必被其占据。

4. 最坏情况举例
摩尔投票法:所有其他元素先出现(如 [1,2,3,4,5,5,5]),但最终仍会收敛到多数元素。

5. 空间复杂度对比
摩尔投票法(O(1))优于哈希表法(O(n)),是最优解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值