9.荷兰国旗

问题一

给定一个数组arr,和一个数num,请把小于等于num的数放在数 组的左边,大于num的数放在数组的右边。
要求额外空间复杂度0(1),时间复杂度0(N)

给定一个小于等于区域,遍历,如果当前数小于等于num,则当前数和小于等于把区域紧挨着的下一个位置数字交换,小于等于区域顺序扩张一个数;如果当前数大于num,则继续遍历。如下代码:minuteArray是核心函数

在这里插入图片描述

代码展示部分保证除了包之外整个代码拷贝过去是可以正常运行的
代码如下:

package yzy.algorithm;

public class dutchFlag {
    //给定一个数组arr,和一个数num,请把小于等于num的数放在数 组的左边,大于num的数放在数组的右边
    public static void minuteArray(int[] arr, int num){
        int x = -1;  //小于等于区域[0,x]
        int i=0;
        while(i<arr.length){
            if(arr[i]<=num) {
                int tmp = arr[i];
                arr[i] = arr[x + 1];
                arr[x + 1] = tmp;
                x += 1;
            }
            i++;
        }
    }
    //对数器: 生成一个长度范围在[1, size]的任意长度并且任意位置是随机值的数组
    //随机值的范围在:[0, value]
    public static int[] generateRandomArray2(int size, int value) {
        //Math.random()  返回[0, 1)范围中的随机小数
        //(size+1)*Math.random()  [0, size+1)-->[0, size]
        int[] arr = new int[(int)((size+1)* Math.random())+1];  //(size+1)* Math.random()是[0, size]范围中的随机小数
        for(int i=0; i<arr.length; ++i) {
            arr[i] = (int) ((value+1)* Math.random());
        }
        return arr;
    }
    public static void showArr(int[] arr){
        for(int i=0; i<arr.length; ++i){
            System.out.print(arr[i]+" ");
        }
        System.out.println();
    }
    public static void main(String[] args) {
        int num = 5;
        int[] arr = generateRandomArray2(10, 10);
        System.out.print("对数器产生的数组:");
        showArr(arr);
        minuteArray(arr, num);
        System.out.print("结果数组:");
        showArr(arr);
    }
}
问题二(荷兰国旗问题1)

给定一个数组arr,和一个数niwn,请把小于num的数放在数组的 左边,等于num的数放在数组的中间,大于num的数放在数组的 右边。
要求额外空间复杂度0(1),时间复杂度0(N)

解决办法和上述小于等于类似,给定小于区域和大于区域,遍历一遍,遇到小于num的数和小于区域的下一个数交换并扩张小于区域一个位置,如果遇到大于num的数,和大于区域的前一个位置的数交换并扩张大于区域一个数,特别注意,交换后还需判断当前数字是不是小于num。等于的情况下跳过这个数并继续遍历(遍历过程当前位置直到大于区域的前一个结束)。如下代码:dutchflag是核心函数

在这里插入图片描述

package yzy.algorithm;

public class dutchFlag {
    public static void dutchflag(int[] arr, int num){
        int l = -1;  //小于区域[0,x]
        int r = arr.length; //大于区域[r,n)
        int i=0;
        while(i<arr.length && i<r){
            if(arr[i]>num){
                int tmp = arr[i];
                arr[i] = arr[r-1];
                arr[r-1] = tmp;
                r -= 1;
                i--;  //特别注意,交换后还需判断当前数字是不是小于num
            }
            else if(arr[i]<num) {
                int tmp = arr[i];
                arr[i] = arr[l + 1];
                arr[l + 1] = tmp;
                l += 1;
            }
            i++;
        }
    }
    //对数器: 生成一个长度范围在[1, size]的任意长度并且任意位置是随机值的数组
    //随机值的范围在:[0, value]
    public static int[] generateRandomArray2(int size, int value) {
        //Math.random()  返回[0, 1)范围中的随机小数
        //(size+1)*Math.random()  [0, size+1)-->[0, size]
        int[] arr = new int[(int)((size+1)* Math.random())+1];  //(size+1)* Math.random()是[0, size]范围中的随机小数
        for(int i=0; i<arr.length; ++i) {
            arr[i] = (int) ((value+1)* Math.random());
        }
        return arr;
    }
    public static void showArr(int[] arr){
        for(int i=0; i<arr.length; ++i){
            System.out.print(arr[i]+" ");
        }
        System.out.println();
    }
    public static void main(String[] args) {
        int num = 5;
        int[] arr = generateRandomArray2(10, 10);
        arr = new int[]{10, 8, 9, 6, 3, 0, 6};
        System.out.print("对数器产生的数组:");
        showArr(arr);
        dutchflag(arr, num);
        System.out.print("结果数组:");
        showArr(arr);
    }
}

我们对荷兰国旗代码进行改进,使得函数可以操作数组任意区间上的元素,如下代码:核心函数partition在规定时间空间复杂度下完成任务,partiton函数返回值是以数组的形式放回等于num的区间

package yzy.algorithm;

public class dutchFlag {
    public static void swap(int[] arr, int i, int j){
        int tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp;
    }
    //数组下标范围:闭区间
    public static int[] partition(int[] arr, int L, int R, int num){
        int less = L - 1;
        int more = R + 1;
        while(L < more){
            if(arr[L] < num)
                swap(arr, ++less, L++);
            else if(arr[L] > num)
                swap(arr, --more, L);
            else
                L++;
        }
        return new int[] {less+1, more-1};
    }
    //对数器: 生成一个长度范围在[1, size]的任意长度并且任意位置是随机值的数组
    //随机值的范围在:[0, value]
    public static int[] generateRandomArray2(int size, int value) {
        //Math.random()  返回[0, 1)范围中的随机小数
        //(size+1)*Math.random()  [0, size+1)-->[0, size]
        int[] arr = new int[(int)((size+1)* Math.random())+1];  //(size+1)* Math.random()是[0, size]范围中的随机小数
        for(int i=0; i<arr.length; ++i) {
            arr[i] = (int) ((value+1)* Math.random());
        }
        return arr;
    }
    public static void showArr(int[] arr){
        for(int i=0; i<arr.length; ++i){
            System.out.print(arr[i]+" ");
        }
        System.out.println();
    }
    public static void main(String[] args) {
        int num = 5;
        arr = generateRandomArray2(10, 10);
//        arr = new int[]{3, 5, 8, 10, 7, 2 };
        System.out.print("对数器产生的数组:");
        showArr(arr);
        int[] res = partition(arr, 0, arr.length-1, num);
        System.out.println("等于num的区间是["+res[0]+","+res[1]+"]");
        System.out.print("结果数组:");
        showArr(arr);
    }
}



  1. 可以对快排加速 ↩︎

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值