【力扣-Python-75】颜色分类(middle)

75. 颜色分类

给定只包含 0、1、2 的数组(红、白、蓝),要求原地 排序,使0在前、1在中、2在后。要求不能使用库排序,最好只遍历一次

又称为荷兰国旗问题

分析:

  1. 排序?快排 或 归并排序,时间复杂度为O(nlogn)。没有利用到只有3种元素这个条件
  2. 引入一个新数组?扫描原数组,碰到0就放左边,碰到2就放右边,碰到1就跳过,最后把剩下的位置填1。只需扫描一遍数组,但引入了额外数组,不符合原地的要求
  3. 计数法?第一遍扫描数组,分别统计0、1、2各出现了多少次;第二遍直接根据这些计数,把对应数量的0、1、2依次填回数组。时间复杂度为O(n),空间复杂度为O(1),因为只用了3个计数变量。但需要扫描数组两遍
  4. 最优解法:三指针法。只需要一次遍历,时间复杂度为O(n),空间复杂度为O(1)

三指针法的思路:

  1. 用三个指针,left 指向0区域的右边界,right 指向2区域的左边界,i 用来遍历数组
  2. 初始时,left 和 i 都指向数组开头,right 指向数组末尾
  3. i 遍历每个元素时,如果遇到0,就和 left 位置交换,然后 left 和 i 都往右移动;如果遇到2,就和 right 位置交换,right往左移动,但 i 不动(因为换过来的元素还没有检查);如果遇到1,就直接跳过,i 往右移动
  4. 直到 i 移动到超过了 right,遍历结束,排序完成

三指针法的巧妙之处在于:遍历过程中始终维护3个区域,left左边全是0,right右边全是2,中间是1和待处理的元素

python 复制代码
class Solution:
    def sortColors(self, nums: List[int]) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        i = 0
        left, right = 0, len(nums)-1
        while i <= right:
            if nums[i] == 0:    # 0应该去左边,跟left交换
                tmp = nums[left]
                nums[left] = nums[i]
                nums[i] = tmp
                # 交换后两者同时右移
                i += 1
                left += 1
            elif nums[i] == 2:   # 2应该去右边,跟right交换
                tmp = nums[right]
                nums[right] = nums[i]
                nums[i] = tmp
                right -= 1   # right左移。注意i不动,因为换过来的数字还需要处理
            else:
                i += 1
        return nums
相关推荐
naruto_lnq5 分钟前
泛型编程与STL设计思想
开发语言·c++·算法
踩坑记录20 分钟前
leetcode hot100 94. 二叉树的中序遍历 easy 递归 dfs
leetcode
2301_8213696121 分钟前
用Python生成艺术:分形与算法绘图
jvm·数据库·python
zxsz_com_cn25 分钟前
设备预测性维护算法分类及优劣势分析,选型指南来了
算法·分类·数据挖掘
机 _ 长37 分钟前
YOLO26 改进 | 基于特征蒸馏 | 知识蒸馏 (Response & Feature-based Distillation)
python·深度学习·机器学习
m0_748708051 小时前
C++中的观察者模式实战
开发语言·c++·算法
然哥依旧1 小时前
【轴承故障诊断】基于融合鱼鹰和柯西变异的麻雀优化算法OCSSA-VMD-CNN-BILSTM轴承诊断研究【西储大学数据】(Matlab代码实现)
算法·支持向量机·matlab·cnn
qq_537562671 小时前
跨语言调用C++接口
开发语言·c++·算法
Tingjct1 小时前
【初阶数据结构-二叉树】
c语言·开发语言·数据结构·算法
C雨后彩虹1 小时前
计算疫情扩散时间
java·数据结构·算法·华为·面试