面试题——过桥

面试题——过桥

题目

有4个人过桥。一个要1分钟,一个要2分钟,一个要5分钟,最后一个要10分钟。桥一次只能过两个人,因为天黑了,过桥必须使用手电筒,但是只有一个手电筒。问题:如何用最少的时间让4个人过桥?

分析

  1. 采用优先级队列存储每个人过桥的时间,由于优先级队列每次取出的元素都是优先级最高的,所以可以无序存储。
  2. 编写过桥和计时两个方法来完成整个过程。由于桥每次只能过两个人,所以需要取出两个元素,其次,要计算最短时间,所以需要获取过桥时间最快的人的用时。所以需要优先获取第一次元素(即过桥用时最短的),且需要记录过桥的次数,在最后一次过桥后,用时最短的人不需要再返回桥头。

编程实现

import java.util.Arrays;
import java.util.List;
import java.util.PriorityQueue;

public class CrossBrigeDemo {

    // 计时器,表示过桥的用时
    private int totalTime = 0;

    /**
     * 过桥
     * 
     * @param priorityQueue
     */
    public void crossBrige(PriorityQueue<Integer> priorityQueue) {

        int index = 0; // 表示第几次过桥
        int lastIndex = priorityQueue.size() - 1; // 表示最后一次过桥
        int first = priorityQueue.peek(); // 获取队列中第一个元素
        while (priorityQueue.peek() != null) {

            if (index == 0) {
                priorityQueue.remove();
                index++;
                continue;
            }
            index++;
            // 移除并获取队列中头元素
            int node = priorityQueue.remove();

            count(first, node, index, lastIndex);

        }

    }

    /**
     * 计时
     * 
     * @param first
     * @param node
     * @param index
     * @param lastIndex
     */
    public void count(int first, int node, int index, int lastIndex) {

        // 如果最后一次过桥,不需要再记录返回的时间
        int crossBrigeTime = index == lastIndex ? node : first + node;
        totalTime += crossBrigeTime;

    }

    public static void main(String[] args) {

        // 用于存储每个人过桥的用时,可以是无序的
        List<Integer> mins = Arrays.asList(2, 5, 10, 1);
        // 用优先级队列来存储每个人的过桥用时,并按优先级排序
        PriorityQueue<Integer> priorityQueue = new PriorityQueue<Integer>();
        priorityQueue.addAll(mins);

        CrossBrigeDemo t = new CrossBrigeDemo();

        t.crossBrige(priorityQueue);

        System.out.println(t.totalTime);

    }

}

源代码链接:https://github.com/myNameIssls/javase-study/blob/master/javase-interviewcase/src/main/java/cn/tyrone/javase/interviewcase/CrossBrigeDemo.java

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值