• 笔试算法题目,奶牛排队喝水


    题目:

    题目描述 
    有N(1≤N≤1000)头奶牛,它们都被标上一个优先等级编号:1,2或3。用来表示它们喝水时的优先次序,编号为l的最优先,编号为2的其次,编号为3的最后。每天奶牛开始时排成一行,但总是很乱,需要你把它们重新排成编号为1的奶牛在最前面,编号为2的其次,编号为3的奶牛在最后。你能计算出最少需要多少的交换次序来完成这次重排吗?

    输入 
    第1行:1个整数N; 
    第2至N+I行:第i+l行有一个整数表示开始队列中第i头奶牛的编号。

    输出 
    1行,只一个整数,表示最少需要交换次数。

    样例输入


    2 2 1 3 3 3 2 3 1

    样例输出

    4

    思路:在读入的时候记录一下1 2 3三个数的数目,然后就可以确定排完序之后他们的界限,然后从1的区域开始扫,扫到2就优先去2的区域找,找不到就去3的区域找,扫到3同理,这样就能保证每一次交换都是最优的,将2区域扫完之后也就完成了所有的交换。如果在1的区扫描到4则同样优先到4的区寻找1,找不到的话从“1的区和4的区”的之外所有区进行寻找,最后交换。

    
    
    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.hustoj.com/oj/problem.php?id=1056
  • 相关阅读:
    《objective-c基础教程》学习笔记(三)—— 从结构体到面向对象
    《objective-c基础教程》学习笔记(二)—— for循环的基本应用
    《objective-c基础教程》学习笔记 (一)—— 开发环境配置和简单类型输出
    asp.net mvc 3.0 知识点整理 ----- (4).asp.net mvc 3 和asp.net mvc 4 对比
    git简单使用(上篇)
    git简单使用(下篇)
    Spring核心概念之Ioc
    "注解"的用法
    struts2进阶篇(3)
    struts2进阶篇(2)
  • 原文地址:https://www.cnblogs.com/leodaxin/p/7400470.html
Copyright © 2020-2023  润新知