数组-链表--乘车按序就座

描述

我们规定乘坐公共交通工具时,正常情况下乘客按序列号 number 的升序顺序排队就座,当乘客中有年龄 age 小于 5 岁(不含 5 岁)的幼儿乘客或是年龄 age 大于 60 岁(不含 60 岁)的老年人乘客时,优先按序就座。现在给你一个乘客列表,请你安排他们按序就座,结果请通过调用 System.out.println 方法进行输出。

样例

样例一
输入:

Jack 21
Jimi 69
July 52
July 42
Jane 70

输出:

number = 1, name = Jimi, age = 69
number = 4, name = Jane, age = 70
number = 0, name = Jack, age = 21
number = 2, name = July, age = 52
number = 3, name = July, age = 42

样例二
输入:

LingHu 65
Haly 59
Jack 24
Jane 2
Fualy 36

输出:

number = 0, name = LingHu, age = 65
number = 3, name = Jane, age = 2
number = 1, name = Haly, age = 59
number = 2, name = Jack, age = 24
number = 4, name = Fualy, age = 36

解题思路

题目要求:

  1. 乘客年龄 age 小于5岁或是大于60岁的乘客,优先按序就座
  2. 乘客需要按序列号 number 的升序顺序排队就坐

方法一

根据题目要求,我们可以通过两个列表来分别按序列号 number 的升序顺序存储优先乘客和非优先乘客的名单,最后先输出优先乘客再输出非优先乘客即可。

List<Person> preList = new ArrayList<>();
List<Person> aftList = new ArrayList<>();

// 遍历list 对其中的Person对象逐一进行判断
for (Person p : list) {
    if (p.age < 5 || p.age > 60) {
        preList.add(p);
    } else {
        aftList.add(p);
    }
}

方法二

同样地,我们也可以通过链表来实现优先有序排列。具体链表的实现,我们可以用到Java提供的 LinkedList 类来解决。

// 新建一个链表 便于插入操作
LinkedList<Person> newList = new LinkedList<>();

按照题目所要求的,我们可以遍历列表中的所有乘客,如果该乘客符合条件,就将其插入到链表的前端;否则就插入到链表的后端。同时,我们也需要一个变量来记录符合条件的人数,以便后续插入新的符合条件的人。

// 用于存储符合条件的人数
int preCount = 0;
// 遍历list中的所有Person对象
for (Person p : list) {
    // 如果年龄符合优先条件
    if (p.age < 5 || p.age > 60) {
        // 如果链表为空
        if (newList.size() < 1) {
            // 将符合优先条件的放到第一个
            newList.addFirst(p);
            // 记录符合条件的人数
            preCount++;
        } else {
            // 在上一个符合条件的人后面插入
            newList.add(preCount, p);
            preCount++;
        }
    } else {
        // 如果年龄不符合条件
        // 则在链表末尾进行插入操作
        newList.addLast(p);
    }
}

最后,同 方法一 将 newList 中的 Person 对象遍历输出即可。


题解代码

方法一

Solution.java

import java.util.*;

public class Solution {
    public void priority(List<Person> list) {
        // write your code here
        List<Person> preList = new ArrayList<>();
        List<Person> aftList = new ArrayList<>();

        // 遍历list 对其中的Person对象逐一进行判断
        for (Person p : list) {
            if (p.age < 5 || p.age > 60) {
                preList.add(p);
            } else {
                aftList.add(p);
            }
        }

        for (Person p : preList) {
            System.out.println(p.toString());
        }
        for (Person p : aftList) {
            System.out.println(p.toString());
        }
    }

}

方法二

Solution.java

import java.util.*;

public class Solution {
    public void priority(List<Person> list) {
        // write your code here
        // 新建一个链表 便于插入操作
        LinkedList<Person> newList = new LinkedList<>();

        // 用于存储符合条件的人数
        int preCount = 0;
        // 遍历list中的所有Person对象
        for (Person p : list) {
            // 如果年龄符合优先条件
            if (p.age < 5 || p.age > 60) {
                // 如果链表为空
                if (newList.size() < 1) {
                    // 将符合优先条件的放到第一个
                    newList.addFirst(p);
                    // 记录符合条件的人数
                    preCount++;
                } else {
                    // 在上一个符合条件的人后面插入
                    newList.add(preCount, p);
                    preCount++;
                }
            } else {
                // 如果年龄不符合条件
                // 则在链表末尾进行插入操作
                newList.addLast(p);
            }
        }

        for (Person p : newList) {
            System.out.println(p.toString());
        }
    }

}

知识要点

1. 队列

队列是一种由数组和链表作为底层构造的只暴露头和尾操作API的数据结构。队列的特性是:先进先出。

2. 双端队列

双端队列(Deque)是Double Ended Queue的缩写,顾名思义就是队列的两个端口都能进出。

Deque的实现类是 LinkedList ,ArrayDeque 和 LinkedBlockingDeque ,其中 LinkedList 是最常用的。

大多数Deque既可以是有容量限制的,也可以是无固定容量限制。

双端队列的插入、删除和检查方法各有两种形式:

第一个元素(头部)最后一个元素(尾部)
抛出异常特殊值抛出异常特殊值
插入addFirst(e)offerFirst(e)addLast(e)offerLast(e)
删除removeFirst()pollFirst()removeLast()pollLast()
检查getFirst()peekFirst()getLast()peekLast()

3. LinkedList实现Deque

LinkedList 是一个在双向队列基础上搭建的双向链表,其关键方法主要有:

  • addFirst(E):在队头添加元素。
  • addLast(E):在队尾添加元素。
  • E removeFirst():删除队头元素。
  • E removeLast():删除队尾元素。

这些方法都是通过操作成员变量 first 和 last 来实现的。first 和 last 的类型是私有类 Node<E> 。实现很简洁,Java 代码如下所示:

private static class Node<E> {
    E item;
    Node<E> next;
    Node<E> prev;
   
    Node(Node<E> prev, E element, Node<E> next) {
        this.item = element;
        this.next = next;
        this.prev = prev;
    }
}

构造方法中清晰体现了它们的初始化过程。这样就能很好地理解之前提及的四个方法是如何实现了。

比如,addLast(E) ,新建一个 Node 结点 n,数据域为方法形参,n.prev 设置为当前的 last,last.next 设置为 n,然后 last=n ,即可完成需求。其他方法的实现原理类似。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值