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

前言

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


一、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) 双指针技巧、原地交换
相关推荐
夏日听雨眠2 小时前
排序(选择排序 ,冒泡排序,归并排序)
数据结构·算法·排序算法
凯瑟琳.奥古斯特2 小时前
操作系统核心结构解析
java·开发语言·c++·python·职场和发展
June bug2 小时前
【AI赋能测试笔记】5基于文档用例生成系统及skills
笔记·功能测试·职场和发展·测试用例·学习方法
珠海西格电力2 小时前
零碳园区的能源成本优势具体体现在哪些方面
大数据·人工智能·算法·架构·能源
Donk_672 小时前
Shell 数组实践
linux·算法·bash
数智工坊3 小时前
【DACS论文阅读】跨域混合采样如何让语义分割模型从合成数据无缝迁移到真实世界
论文阅读·人工智能·算法·机器人·无人机
And_Ii3 小时前
LeetCode 026. 重排链表
算法·leetcode·链表
心中有国也有家3 小时前
catlass 算子模板库中的 FlashAttention 高性能实现
笔记·算法
是娇娇公主~3 小时前
力扣——146.LRU缓存详解
算法·leetcode·缓存