算法路漫漫(三) 荷兰国旗

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

/**
 * 给定一个数组arr,和一个数num,请把小于等于num的数放在数组的左边,
 *  大于num的数放在数组的右边。要求额外空间复杂度O(1),时间复杂度O(N)
 */
@Slf4j
public class Alg008_SeparateArr {


    @Test
    public void test(){
        for(int i=0;i<5000;i++){
            int[] arr  = generateArr();
            int[] vals = separate(arr, 0);    
            log.info("vals:{}", vals);
        }
    }


    private int[] separate(int[] arr, int target){
        if(arr.length <2){
            return arr ;
        }
        int l =0;
        for(int i=0;i<arr.length;i++){
           if(arr[i] < target){
                swap(arr,l++,i);
           } 
        }
        return arr;

    }


    public static void swap(int[] arr, int i, int j) {
        int tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp;
    }


    private int[] generateArr(){
        return new Random().ints(-100, 100).distinct().limit(20).toArray();
 
    }
    
}

解题思路: 借助一个辅助变量L下标为0, 遍历数组 比较小于sum的值,与L交换,同时L++

2.(荷兰国旗问题)给定一个数组arr,和一个数num,请把小于num的数放在数组的左边,等于num的数放在数组的中间,大于num的数放在数组的右边。要求额外空间复杂度O(1),时间复杂度O(N)

/**
 * 给定一个数组arr,和一个数num,请把小于num的数放在数组的左边,等于num的数放在数组的中间,
 *      大于num的数放在数组的右边。要求额外空间复杂度O(1),时间复杂度O(N)
 */
@Slf4j
public class Alg009_NetherlandsFlag {


    @Test
    public void test(){
        for(int i=0;i<5000;i++){
            int[] arr  = generateArr();
            log.info("result:{}", change(arr, 0, arr.length-1, 0));
        }
    }

    // push the L close to R
    public int[] change(int[] arr, int L,int R,int target){
        int l = L-1;
        int r = R+1;
        while(L < r){
            if(arr[L] < target){
                swap(arr,++l,L++);
            } else if(arr[L] > target){
                swap(arr, --r,L);
            } else {
                L++;
            }
        }
        return arr;
    }

    public static void swap(int[] arr, int i, int j) {
        int tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp;
    }


    private int[] generateArr(){
        return new Random().ints(-100, 100).distinct().limit(20).toArray();
 
    }
    
}

解题思路: 给数组规定左边界和右边界,以及移动的指针i, 一共有三种比较

1. arr[i] < num, i和左边界的下一位交换,同时左边界右扩一位,i++

2. arr[i] == num, i++

3. arr[i] > num, i和右边界的前一位交换,同时右边界左扩一位,i原地不动

原文地址:https://www.cnblogs.com/hlkawa/p/14942911.html