一文了解荷兰国旗问题

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010414589/article/details/89630585

题目描述

我们将乱序的红白蓝三色小球排列成有序的红白蓝三色同颜色在一起的小球组。这个问题之所以叫荷兰国旗,是因为我们将红白蓝三色小球想象成条状物,有序排列后正好组成荷兰国旗。

题目抽象

我们可以把乱序的红白蓝小球看作一个只包含0,1,2三种元素的无序数组,如[1,2,0,2,1,1,0,2,1,2,2,0]。我们希望排序后小于1的排在前面,等于1的排在中间,大于1的排在后面。排序后的效果是[0,0,0,1,1,1,1,2,2,2,2,2]。

更进一步的抽象,一个整型数组arr,和一个整数num,请把小于num的数放在数组的左边,等于num的数放在数组的中间,大于num的数放在数组的右边。

解题思路

我们将数组分为三部分,从头开始遍历数组,遇到小于指定值的放在左边部分,等于指定值的放在中间部分,大于指定值的放在右边部分。通过一次遍历即完成了题目的要求。(起始状态下左部和右部均为空,元素均在中部)

具体做法如下:

已知指定的值为 num,数组 array 的起始和末尾下标分别是 l 和 r 。

我们设置两个指针left和right分别指向左部最后一个位置和右部第一个位置,起始状态left和right指向 l-1 和 r+1 ,表示左部和右部元素为空。然后设置一个指针 cur 来从头遍历数组。

  • 当遇到一个值小于num时,表示该值应该位于左部,就让该值和中部第一个值进行交换,然后left右移一位,cur右移一位。(左部就增加了一个元素,left右移一位后仍指向左部最后一个位置)
  • 当遇到一个值大于num时,表示该值应该位于右部,就让该值和中部最后一个值进行交换,然后right 左移一位,cur保持不变。(右部就增加了一个元素,right左移一位后仍指向右部第一个位置。cur 不移动是因为交换后的元素不确定是位于中部,所以不移动然后在下一轮做判断)
  • 当遇到一个值等于num时,表示该值应该位于中部,此时左部和右部都不会增加元素,所以left和right 保持不变,cur 右移一位。
  public static int[] partition(int[] array,int l,int r,int num){
        int left = l-1;
        int right = r+1;
        int cur = l;
        while(cur<right){
            if(array[cur]<num){
                swap(array,cur++,++left);
            }else if(array[cur]>num){
                swap(array,cur,--right);
            }else{
                cur++;
            }
        }
        return new int[]{left+1,right-1};
    }

喜欢本文的朋友们,欢迎关注我的订阅号
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/u010414589/article/details/89630585