描述
我们规定乘坐公共交通工具时,正常情况下乘客按序列号 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
解题思路
题目要求:
- 乘客年龄
age
小于5岁或是大于60岁的乘客,优先按序就座 - 乘客需要按序列号
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
,即可完成需求。其他方法的实现原理类似。