import java.util.*;/** * Created by Daxin on 2017/8/19. * <p/> * 奶牛排队饮水问题 * 输入:n牛的数目,然后n个整数表示牛的序号 * 输出:输出交换最少次数 * <p/> * 例如一个测试用例:9<br> * 2,2,1,3,3,3,2,3,1<br> * 输出:4 * *在线题目地址:http://www.hustoj.com/oj/problem.php?id=1056 * * */public class CattleSortWater {    public static void main(String[] args) {//        int[] nums = {2, 2, 1, 3, 3, 3, 2, 3, 1};        Scanner cin = new Scanner(System.in);        int n = cin.nextInt();        int[] nums = new int[n];        for (int i = 0; i < n; i++) {            nums[i] = cin.nextInt();        }        System.out.println(solve(nums));//        System.out.println(Arrays.toString(nums));    }    public static int solve(int[] nums) {        int result = 0;        Map<Integer, Integer> wcount = new TreeMap<>();        Map<Integer, Integer> range = new TreeMap<>();        for (int num : nums) {            Integer tmp = wcount.get(num);            wcount.put(num, tmp == null ? 1 : tmp + 1);        }        Set<Integer> set = wcount.keySet();        int pre = 0;        for (int i : set) {            int tmp = wcount.get(i) + pre;            range.put(i, tmp);            pre = tmp;        }        for (int num : set) {            int times = wcount.get(num);            int ran = range.get(num);            for (int i = ran - 1, t = times; t > 0; t--, i--) {                if (nums[i] != num) {                    int r = get(nums, range.get(nums[i]), wcount.get(nums[i]), num);                    if (r != -1) { //在nums[i] 区间中寻找到了num                        int tmp = nums[r];                        nums[r] = nums[i];                        nums[i] = tmp;                        result++;                    } else {// 在希望区间没有找到,进行余下遇见全扫描                        int rr = getRange(nums, ran, num,range.get(nums[i])-wcount.get(nums[i]),range.get(nums[i]));                        if (rr != -1) {                            int tmp = nums[rr];                            nums[rr] = nums[i];                            nums[i] = tmp;                            result++;                        }                    }                }            }        }        return result;    }    /**     *     * @param nums 数组     * @param range 结束的下标     * @param times 出现的次数,range-times就是起始下标     * @param expect 希望查找的希望值     * @return     */    public static int get(int[] nums, int range, int times, int expect) {        for (int i = range - 1, t = times; t > 0; t--, i--) {            if (nums[i] == expect) {                return i;            }        }        return -1;    }    /**     *     * @param nums 数组     * @param start 查找的起始位置,结束位置是数组的结束     * @param expect 期望寻找到的值     * @param exceptStart 排除区域的起始下标     * @param exceptEnd 排除区域的结束下标     * @return 返回下标     */    public static int getRange(int[] nums, int start, int expect,int exceptStart,int exceptEnd) {        for (; start < nums.length; start++) {            if(start>=exceptStart&&start<exceptEnd)                continue;            if (nums[start] == expect) {                return start;            }        }        return -1;    }}原文:http://www.cnblogs.com/wangsicongde/p/7576890.html