荷兰国旗问题

文章介绍了荷兰国旗问题,即对包含三种数字的数组进行分类。通过一次扫描和快速排序的partition过程,利用常数空间解决此问题。算法的核心是定义分区边界并迭代数组,将0、1、2分别放在正确的位置,过程中不需要递归。提供的Java代码示例展示了如何实现这个算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

point:仅使用常数空间的一趟扫描算法

一、什么是荷兰国旗问题

对只含有三种数字的数组进行分类或者排序称为荷兰国旗问题

二、如何解决此类问题

解决这类问题借助快速排序partition过程的一趟扫描法。(重点在于设计循环不变量)
partition的过程就是随机选择一个基准值,然后经过一次扫描通过交换不同位置的元素使得数组大小分成三部分,分别是:小于基准值,等于基准值和大于基准值。

那为什么只需要一次就够呢?(即无需递归实现)
因为题目中的三个数是无差别的,也就是说0和0不需要排序

三、如何实现

实现过程:
1.定义分区的边界
首先定义两个指针p0和p2分别指向头和尾
然后是循环变量i用于遍历数组
划分:
all in [0, p0) = 0
all in [p0, i) = 1
all in (p2, len - 1] = 2
需要注意的是,区间划分不同,循环的条件也不同

2.在遍历开始前这三个区间都为空

3.例如2,0,2,1,1,0
i从0开始遍历,遇到2。2应该在最后一个区间,所以该2与p2所指的数进行交换。
由于所有的2都要在p2之后,所以p2–
而交换过来的数是0,而0都在p0指针之前,所以p0++
最后i向前移动,移动后遇到的数还是0。为了满足p0的定义,p0++
然后i向前,遇到2,所以与p2所指位置的数交换,p2–
i继续向前遇到1,1既不在第一个区间也不在最后一个区间,所以不需要移动,只需要让i继续向前,同理。
最后i>p2,所以结束循环。

import java.util.Arrays;


public class Solution {

    public void sortColors(int[] nums) {
        int len = nums.length;
        if (len < 2) {
            return;
        }
        // 循环终止条件是 i > two,那么循环可以继续的条件是 i <= two
        // 为了保证初始化的时候 [0, p0) 为空,设置 p0 = 0,
        // 所以下面遍历到 0 的时候,先交换,再加
        int p0 = 0;

        // 为了保证初始化的时候 (p2, len - 1] 为空,设置 p2 = len-1
        int p2 = len-1;
        int i = 0;
        // 当 i > p2 上面的三个子区间正好覆盖了全部数组
        // 因此,循环可以继续的条件是 i <= two
        while (i <= two) {
            if (nums[i] == 0) {
                swap(nums, i, p0);
                p0++;
                i++;
            } else if (nums[i] == 1) {
                i++;
            } else {
                swap(nums, i, two);
                p2--;
            }
        }
    }

    private void swap(int[] nums, int index1, int index2) {
        int temp = nums[index1];
        nums[index1] = nums[index2];
        nums[index2] = temp;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值