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

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;

    }

}

时间: 2024-08-24 01:08:47

笔试算法题目,奶牛排队喝水的相关文章

[Offer收割]编程练习赛11 题目4 : 排队接水

时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 有n个小朋友需要接水,其中第i个小朋友接水需要ai分钟. 由于水龙头有限,小Hi需要知道如果为第l个到第r个小朋友分配一个水龙头,如何安排他们的接水顺序才能使得他们等待加接水的时间总和最小. 小Hi总共会有m次询问,你能帮助他解决这个问题吗? 假设3个小朋友接水的时间分别是2,3,4.如果他们依次接水,第一位小朋友等待加接水的时间是2,第二位小朋友是5,第三位小朋友是9.时间总和是16. 输入 第一行一个数T(T<=1

算法之美一书附录中笔试面试题目参考答案

探秘算法世界,求索数据结构之道:汇集经典问题,畅享编程技法之趣:点拨求职热点,敲开业界名企之门.<算法之美--隐匿在数据结构背后的原理>全文目录."45个算法"目录."22个经典问题目录",请见如下链接: 算法之美隆重上市欢迎关注(更有三重好礼) http://blog.csdn.net/baimafujinji/article/details/50484348 *本书附录中的笔试面试题目主要从我之前的系列博文<常见C++笔试题目整理(含答案)&g

【贪心】排队接水

问题 C: [贪心]排队接水 时间限制: 1 Sec  内存限制: 128 MB提交: 38  解决: 20[提交][状态][讨论版] 题目描述 有n个人在一个水龙头前排队接水,假如每个人接水的时间为Ti,请编程找出这n个人排队的一种顺序,使得n个人的平均等待时间最小. 输入 共两行,第一行为n:第二行分别表示第1个人到第n个人每人的接水时间T1,T2,…,Tn,每个数据之间有1个空格. 输出 有两行,第一行为一种排队顺序,即1到n的一种排列:第二行为这种排列方案下的平均等待时间(输出结果精确到

笔试算法题(06):最大连续子数组和 &amp; 二叉树路径和值

出题:预先输入一个整型数组,数组中有正数也有负数:数组中连续一个或者多个整数组成一个子数组,每个子数组有一个和:求所有子数组中和的最大值,要求时间复杂度O(n): 分析: 时间复杂度为线性表明只允许一遍扫描,当然如果最终的最大值为0表明所有元素都是负数,可以用线性时间O(N)查找最大的元素.具体算法策略请见代码和注释: 子数组的起始元素肯定是非负数,如果添加的元素为正数则记录最大和值并且继续添加:如果添加的元素为负数,则判断新的和是否大于0,如果小于0则以下一个元素作为起始元素重新开始,如果大于

排队接水

题目描述 有n个人在一个水龙头前排队接水,假如每个人接水的时间为Ti,请编程找出这n个人排队的一种顺序,使得n个人的平均等待时间最小. 输入输出格式 输入格式: 输入文件共两行,第一行为n:第二行分别表示第1个人到第n个人每人的接水时间T1,T2,…,Tn,每个数据之间有1个空格. 输出格式: 输出文件有两行,第一行为一种排队顺序,即1到n的一种排列:第二行为这种排列方案下的平均等待时间(输出结果精确到小数点后两位). 输入输出样例 输入样例#1: 10 56 12 1 99 1000 234

笔试算法题(42):线段树(区间树,Interval Tree)

议题:线段树(Interval Tree) 分析: 线段树是一种二叉搜索树,将一个大区间划分成单元区间,每个单元区间对应一个叶子节点:内部节点对应部分区间,如对于一个内部节点[a, b]而言,其左子节点表示的区间为[a, (a+b)/2],其右子节点表示的区间为[1+(a+b)/2, b]: 对于区间长度为N的线段树,由于其单元节点都是[a, a]的叶子节点,所以其叶子节点数为N,并且整棵树为平衡二叉树,所以总节点数为2N-1,树的深度为log(N)+1: 插入操作:将一条线段[a, b]插入到

【算法题目】2048游戏的最少时间 最大数

1.搜狐技术中心笔试遇到的题目 描述:假设滑动一次需要1秒,新出现是4的概率很小可以忽略,加到2048的需要的时间最少是多少? 分析:全部由2相加,得到4需要1次相加,得到8需要3次相加--得到2048需要1024-1次相加 (1024-1)/60约为17分钟 实际上,在进行加法前可能需要等待 新元素2的出现,那么估算的最少时间必然大于17分钟 具体枚举: 目标 需要时间 ? 1 2 3 4 5 6 2      0 4      3 8      5 16    10 32    20   

luogu P1223 排队接水 x

P1223 排队接水 题目描述 有n个人在一个水龙头前排队接水,假如每个人接水的时间为Ti,请编程找出这n个人排队的一种顺序,使得n个人的平均等待时间最小. 输入输出格式 输入格式: 输入文件共两行,第一行为n:第二行分别表示第1个人到第n个人每人的接水时间T1,T2,…,Tn,每个数据之间有1个空格. 输出格式: 输出文件有两行,第一行为一种排队顺序,即1到n的一种排列:第二行为这种排列方案下的平均等待时间(输出结果精确到小数点后两位). 输入输出样例 输入样例#1: 10 56 12 1 9

洛谷 试炼场 P1233 排队接水 (排序,贪心)

一道水题.... 链接:https://www.luogu.org/problem/show?pid=1223 题目描述 有n个人在一个水龙头前排队接水,假如每个人接水的时间为Ti,请编程找出这n个人排队的一种顺序,使得n个人的平均等待时间最小. 输入输出格式 输入格式: 输入文件共两行,第一行为n:第二行分别表示第1个人到第n个人每人的接水时间T1,T2,-,Tn,每个数据之间有1个空格. 输出格式: 输出文件有两行,第一行为一种排队顺序,即1到n的一种排列:第二行为这种排列方案下的平均等待时