算法:公交让座问题

  • Post author:
  • Post category:其他


算法题:

解决实际应用问题:公交车让座问题

一辆公交车,有n个座位(n<100),陆续有乘客上车和下车,新乘客上车时,如果座位全满,新上来的乘客的优先级如果比座位上的某些人大,那么就需要选出优先级比他低的人给他让座,同样的,座位上有人到站下车空出了座位,需要在无座的人里面选出优先级高的人入座

座位优先级规则(先幼后老再中年):按年龄最小(年龄相同再按上车时间最先上车优先)安排10岁及以下的儿童入座,如果没有合适的儿童,再安排车上年龄最大的(年龄相同按上车时间最先上车的优先)的人入坐

使用一个二维数组来代表上下车的人 [[姓名,年龄,“上车/下车”],…], 姓名不重复, 数组长度小于10000,年龄小于200,一个人最多只有一次上车和下车记录

# 要求计算出主动让座(正常下车不算让座)的人次姓名清单

def busPrioritySeats(queue: list, n: int) -> list:

# to be implemented

return []

    queue = [["大学生朱菲菲", 20, "上车"],
    ["中年抗压男王五", 40, "上车"],
    ["小学生张三", 6, "上车"],
    ["村花罗密欧", 18, "上车"],
    ["小学生张三", 6, "下车"],
    ["大学生朱菲菲", 20, "下车"],
    ["退伍大爷牛七", 60, "上车"]];

    print(busPrioritySeats(queue, 2))
    # 算法说明:
    # 前2个都有位置入座                    -> 有座:["大学生朱菲菲","中年抗压男王五"],无座位:[] , 让座记录:[]
    # 小学生张三 来了,大学生 主动让座     -> 有座:["小学生张三","中年抗压男王五"], 无座位:["大学生朱菲菲"] , 让座记录:["大学生朱菲菲"]
    # 村花罗密欧来了,村花 无座站岗           -> 有座:["小学生张三","中年抗压男王五"], 无座位:["大学生朱菲菲","村花罗密欧"] , 让座记录:["大学生朱菲菲"]
    # 小学生张三下车,空出座位给大学生朱菲菲入座 -> 有座:["中年抗压男王五","大学生朱菲菲"], 无座位:["村花罗密欧"] , 让座记录:["大学生朱菲菲"]
    # 大学生朱菲菲下车,空出座位给村花罗密欧入座 -> 有座:["中年抗压男王五","村花罗密欧"], 无座位:[] , 让座记录:["大学生朱菲菲"]
    # 退伍大爷牛七上车,村花罗密欧 主动让座     -> 有座:["退伍大爷牛七","中年抗压男王五"], 无座位:["村花罗密欧"] , 让座记录:["大学生朱菲菲","村花罗密欧"]

使用优先队列的比较器详解见前文

PriorityQueue优先队列中比较器Comparator的使用

public class Main {

    public static void main(String[] args) {
        String[][] peoples  = {{"大学生朱菲菲", "20","上车"},
            {"中年抗压男王五", "40", "上车"},
            {"小学生张三", "6", "上车"},
            {"村花罗密欧", "18","上车"},
            {"小学生张三", "6", "下车"},
            {"大学生朱菲菲", "20", "下车"},
            {"退伍大爷牛七", "60", "上车"}};

        List<String[]> res = busPrioritySeats(peoples,2);

        for(String[] s:res){
            System.out.println(s[0]);
        }

        System.out.println(" ");
    }

    public static int cmp(String[] o1, String[] o2){
        int age1 = Integer.parseInt(o1[1]);
        int age2 = Integer.parseInt(o2[1]);
        //当年龄相同时,我们按照上车的顺序
        //拿上策划的顺序是什么呢?之前说过,如对的时候永远是那新的那个值和其他旧的值进行比较
        //所以o1永远是新来的,所以如果相等,o1是最应该让座的人
        //之前说过入队时想让o1上去,return -1;
        if(age1 == age2){
            return -1;
        }
        //不相等时就开始比较年龄
        else{
            //两者年龄都小于等于10,应该比较大的先让座
            //类似于建立大顶堆,所以 return o2-o1;
            if(age1<=10 && age2<=10){
                return age2-age1;
            }
            //两者年龄都大于10,应该比较小的先让座
            //类似于建立小顶堆,所以 return o1-o2;
            else if(age1>10 && age2>10){
                return age1 - age2;
            }
            //一个小于等于10,一个大于10,也是应该大的先让座
            //类似于建立大顶堆,return o2-o1;
            //应该和第一种合在一起,但是为了观看清晰,就不合了
            else{
                return age2-age1;
            }
        }
    }

    public static List<String[]> busPrioritySeats(String[][] peoples, int n){

        List<String[]> res = new ArrayList< String[]>();

        PriorityQueue<String[]> seats = new PriorityQueue< String[]>(new Comparator<String[]>() {
            @Override
            public int compare(String[] o1, String[] o2) {
                return cmp(o1,o2);
            }
        });
        PriorityQueue<String[]> stand = new PriorityQueue<String[]>(new Comparator<String[]>() {
            @Override
            public int compare(String[] o1, String[] o2) {
                return -cmp(o1,o2);
            }
        });


        for(String[] s: peoples){
            if("上车".equals(s[2])){
                if(seats.size() < n){
                    seats.offer(s);
                }else{
                    String[] people = seats.peek();

                    //通过比较如果不应该让坐就直接将people放如站着的队伍
                    if(cmp(s,people)<0){
                        stand.offer(s);
                    }else{
                        res.add(people);
                        seats.poll();
                        seats.offer(s);
                        stand.offer(people);
                    }
                }
            }else {
                //people没座位,从stand中移除
                String[] temp = valid(stand,s[0]);
                if(temp != null){
                    stand.remove(temp);
                }
                //people有作为,从seats中移除并从stand中找出一个放到seats中
                else{
                    temp = valid(seats,s[0]);
                    seats.remove(temp);
                    if(stand.size() > 0){
                        seats.offer(stand.poll());
                    }
                }
            }
        }
        return res;
    }

    public static String[] valid(PriorityQueue<String[]> queue,String name){
        for(String[] s:queue){
            if(s[0].equals(name)){
                return s;
            }
        }
        return null;
    }
    
}



版权声明:本文为qq_41845823原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。