オランダの旗を持つ小さな問題と課題

小型で問題
の配列では、アレイと小さなと呼ばれる、現在のカウントよりも各番号の左まで追加します。小さな配列を探していると。例:
[1,2,3,4]
左側よりも小さいつの番号、なし;
2より左側の少数2、1、
数3よりも小さい3左側に、1、2、
4、左4の数よりも少ないです、1,2,3、;
そう小さく、1 + 1 + 2 + 1 + 2 + 3 = 10
アイデア:思考のマージソート、2列に統計番号の右側にプロセスをマージ左の数よりも大きいです最終合計数を乗じ、この数、その後にすることができます。


public class work1 {
    public static int mergeSort(int[] arr, int left, int right) {
        if(left == right)
            return 0;
        int mid = left + (right - left) / 2;
        return mergeSort(arr, left, mid) + mergeSort(arr, mid+1, right)
                + merge(arr, left, mid, right);
    }
    public static int merge(int[] arr, int left, int mid, int right) {
        int[] help = new int[right - left +1];
        int i = 0;
        int res = 0;
        int p1 = left;
        int p2 = mid + 1;
        while(p1 <= mid && p2 <= right) {
            //在合并的时候计算右边有多少个元素大于arr[p1],然后arr[p1]与个数相乘后加起来.
            res += arr[p1] < arr[p2]? arr[p1] *(right - p2 + 1) : 0;
            help[i++] = arr[p1] < arr[p2]? arr[p1++] : arr[p2++];
        }
        while(p1 <= mid) {
            help[i++] = arr[p1++];
        }
        while(p2 <= right) {
            help[i++] = arr[p2++];
        }
        for(i = 0; i < help.length; i++)
            arr[left + i] = help[i];
            return res;
    }
    public static void main(String[] args)
    {
        int[] arr = new int[] {1,2,3,4};
        System.out.print("原始数组:");
        for(int i = 0; i < arr.length; i++)
            if(i != arr.length - 1)
            System.out.print(arr[i] + " ");
            else
                System.out.println(arr[i]);
        int sum = mergeSort(arr, 0 ,arr.length - 1);
        System.out.print("小数和:");
        System.out.println(sum);

    }
}

結果:
オランダの旗を持つ小さな問題と課題

オランダフラグ問題:例えば、配列を与え:[334,6,323,44,88,88,56,90]は88の値を与えられ、その後、元の配列状況を有していてもよい処理した後である:[56、6、44 、88、88、323、90、334]、不要な部分88は、部分88は、左右の添字4等分に戻るように命じ必要より大きい秩序よりも小さくないことに留意されたい、すなわち、[3 、4]
アイデア:速い行のアイデアは、二つのポインタが少ないNUM NUM間隔少ないnum個以上のスキャンを完了するために、左より、num個の右よりも大きいが、左と右の必要性がない命じ、より大きなのより左側と右側の間隔を維持するために使用されています。

import java.util.Scanner;

public class work2 {
    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};
    }
    public static void swap(int[] arr, int i,int j) {
        int tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp;
    } 
    public static void main(String[] args) {
        int[] arr = new int[]{334,6,323,44,88,88,56,90};
        System.out.print("原始数组:");
        for(int i = 0; i < arr.length; i++)
            if(i != arr.length - 1)
                System.out.print(arr[i] + " ");
            else
                System.out.println(arr[i]);
        System.out.print("请输入一个整数:");
        Scanner in = new Scanner(System.in);
        int num = in.nextInt();
        int[] p = partition(arr, 0, arr.length - 1, num);
        System.out.println("partition之后");
        for(int i = 0; i < arr.length; i++)
            if(i != arr.length - 1)
                System.out.print(arr[i] + " ");
            else
                System.out.println(arr[i]);
        System.out.println(num + "的左边界为:" + p[0] + ",右边界为:" + p[1]);
    }
}

結果:
オランダの旗を持つ小さな問題と課題

おすすめ

転載: blog.51cto.com/14472348/2480588