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

前言

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


一、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 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。 我们使用整数 012 分别表示红色、白色和蓝色。 注意:不能使用库函数来排序,必须原地解决。

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

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

  • 定义 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) 双指针技巧、原地交换
相关推荐
Gigavision4 小时前
基于BUAA-MIHR数据集的噪声解耦对比学习算法
人工智能·python·深度学习·算法
鹿角片ljp4 小时前
LeetCode 64:最小路径和复盘|二维 DP 与 ACM 模式完整写法
java·数据结构·算法
彧azz5 小时前
算法设计与分析:贪心与动态规划
数据结构·学习·算法·贪心算法·动态规划
Beyond_System|系统之外6 小时前
【学编程】Python基础编程题100道(21-60)
开发语言·python·算法
漂流瓶jz8 小时前
UVA-1442 洞穴 题解答案代码 算法竞赛入门经典第二版
c++·算法·题解·aoapc·算法竞赛入门经典·uva
圣保罗的大教堂8 小时前
leetcode 835. 图像重叠 中等
leetcode
叠层归一研究院9 小时前
基于极限自指的叠层归一宇宙结构理论——无元外部封闭系统的内生区分模型
人工智能·经验分享·算法·agi
Selvaggia10 小时前
Diffusion Model 的基本原理与模型架构
算法
wabs66612 小时前
关于二叉树【力扣572.另一棵树的子树的思考】
数据结构·c++·算法·leetcode·二叉树
hanlin0312 小时前
刷题笔记:力扣第41题-缺失的第一个正数
笔记·算法·leetcode