两道数组算法题复盘:多数元素 & 颜色分类

前言

今天复盘两道面试高频的数组题,一道是利用摩尔投票算法的经典题「多数元素」 ,另一道是荷兰国旗问题的典型应用「颜色分类」。这两道题分别代表了 "特殊条件下的最优解" 和 "原地排序的双指针技巧",是数组处理中非常实用的算法模板。


一、169. 多数元素(简单)

题目描述

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

核心思路:摩尔投票算法

摩尔投票算法的核心思想是 **"正负抵消"**:因为多数元素的出现次数超过一半,所以它在和其他元素两两抵消后,最终一定会剩下。

  1. 维护一个候选元素 candidate 和它的票数 count
  2. 遍历数组:
    • 若 count == 0,将当前元素设为新的候选
    • 若当前元素等于候选,count++;否则 count--
  3. 遍历结束后,candidate 就是多数元素

完整代码(Java)

java

运行

复制代码
class Solution {
    public int majorityElement(int[] nums) {
        int candidate = nums[0];
        int count = 1;
        for (int i = 1; i < nums.length; i++) {
            if (count == 0) {
                candidate = nums[i];
                count = 1;
            } else if (nums[i] == candidate) {
                count++;
            } else {
                count--;
            }
        }
        return candidate;
    }
}

复杂度分析

  • 时间复杂度:O (n),仅需一次遍历数组
  • 空间复杂度:O (1),仅使用常数额外空间

拓展思考

摩尔投票算法还可以拓展到 "找出数组中出现次数大于 n/3 的元素",最多有两个候选元素,需要两轮遍历:第一轮投票找出候选,第二轮验证是否满足条件。


二、75. 颜色分类(中等)

题目描述

给定一个包含红色、白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。 我们使用整数 0、1 和 2 分别表示红色、白色和蓝色。 注意:不能使用库函数来排序,必须原地解决。

核心思路:双指针(荷兰国旗问题)

这道题的最优解法是三指针原地交换,核心思想是:

  • 定义 p0 指向 0 元素的右边界,p2 指向 2 元素的左边界,curr 指向当前遍历元素
  • 遍历数组:
    • 若 nums[curr] == 0,将其与 nums[p0] 交换,p0++、curr++
    • 若 nums[curr] == 2,将其与 nums[p2] 交换,p2--(此时 curr 不前进,因为交换过来的元素还需要判断)
    • 若 nums[curr] == 1,直接 curr++

完整代码(Java)

java

运行

复制代码
class Solution {
    public void sortColors(int[] nums) {
        int p0 = 0, curr = 0;
        int p2 = nums.length - 1;
        while (curr <= p2) {
            if (nums[curr] == 0) {
                swap(nums, curr, p0);
                p0++;
                curr++;
            } else if (nums[curr] == 2) {
                swap(nums, curr, p2);
                p2--;
            } else {
                curr++;
            }
        }
    }

    private void swap(int[] nums, int i, int j) {
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }
}

复杂度分析

  • 时间复杂度:O (n),仅需一次遍历数组
  • 空间复杂度:O (1),原地交换,未使用额外空间

拓展思考

荷兰国旗问题可以拓展到更多颜色的排序场景,核心思想都是通过指针将元素分区,一次遍历完成排序,避免了多次遍历或额外空间的开销。


两道题对比总结

表格

题目 核心思想 时间复杂度 空间复杂度 关键考点
多数元素 摩尔投票算法(正负抵消) O(n) O(1) 多数元素的定义、投票过程
颜色分类 三指针原地分区(荷兰国旗问题) O(n) O(1) 双指针技巧、原地交换
相关推荐
怪奇云呼军10 分钟前
教育试听预约后没到课,闪电智能 Voice Agent 如何做分层回访?
人工智能·python·算法·云计算·音视频
Nil20816 分钟前
leetcode 416分割等和子集
算法·leetcode·职场和发展
云淡风轻~窗明几净18 分钟前
角谷猜想的进展之三 移动了群山/沸騰的群山 2026-10-10
人工智能·算法·dubbo·图论
ForeverYang201538 分钟前
一种无需训练缺陷数据生成算法--O2MAG
人工智能·深度学习·算法
Pniubi41 分钟前
Agent开发:记忆系统中向量存储的合理安排
职场和发展
xuxigifxfh1 小时前
牛客:HJ170 01序列
java·开发语言·算法·华为机考
朝朝辞暮i1 小时前
C++ 第 33 课:事件循环——spin() 到底在干什么
开发语言·c++·算法
殷色玫瑰2 小时前
AVL树:从平衡因子到四种旋转的完整实现
c语言·数据结构·c++·算法·visualstudio
jidaowansui2 小时前
B3643 图的存储———>数组模拟邻接矩阵
算法
y1su3 小时前
Leetcode 二分模板
java·数据结构·算法·leetcode·排序算法