PAT——1055. 集体照 (比较comparable和comparator的区别)
拍集体照时队形很重要,这里对给定的N个人K排的队形设计排队规则如下:
- 每排人数为N/K(向下取整),多出来的人全部站在最后一排;
- 后排所有人的个子都不比前排任何人矮;
- 每排中最高者站中间(中间位置为m/2+1,其中m为该排人数,除法向下取整);
- 每排其他人以中间人为轴,按身高非增序,先右后左交替入队站在中间人的两侧(例如5人身高为190、188、186、175、170,则队形为175、188、190、186、170。这里假设你面对拍照者,所以你的左边是中间人的右边);
- 若多人身高相同,则按名字的字典序升序排列。这里保证无重名。
现给定一组拍照人,请编写程序输出他们的队形。
输入格式:
每个输入包含1个测试用例。每个测试用例第1行给出两个正整数N(<=10000,总人数)和K(<=10,总排数)。随后N行,每行给出一个人的名字(不包含空格、长度不超过8个英文字母)和身高([30, 300]区间内的整数)。
输出格式:
输出拍照的队形。即K排人名,其间以空格分隔,行末不得有多余空格。注意:假设你面对拍照者,后排的人输出在上方,前排输出在下方。
输入样例:
10 3
Tom 188
Mike 170
Eva 168
Tim 160
Joe 190
Ann 168
Bob 175
Nick 186
Amy 160
John 159
输出样例:
Bob Tom Joe Nick
Ann Mike Eva
Tim Amy John
---------------------------------------------------------------------------------------
具体代码实现:
package com.hone.basical; import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Scanner; /**
* 原题目:https://www.patest.cn/contests/pat-b-practise/1055
* @author Xia
* 可以利用字符串拼接来处理
* 而且决定了得先从最后一排开始战队
*/ public class basicalLevel1055groupPic { public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int N = in.nextInt(); //总人数
int k = in.nextInt(); //k表示排数 List<Person> persons = new ArrayList<>();
int rowPeo = N/k; //第一排的人数
int lastPeo = N-(k-1)*rowPeo; //最后一排的人数
for (int i = 0; i < N; i++) {
Person p = new Person();
p.name = in.next();
p.height = in.nextInt();
persons.add(p);
} Collections.sort(persons,new Person()); int index = persons.size()-1;
String result = "";
//先从最后一排开始战队
int i = k;
result = persons.get(index).name;
index--;
for (int j = 1; j < lastPeo; j++) {
if (j%2==1) {
result=persons.get(index--).name+" "+result;
}else {
result=result+" "+persons.get(index--).name;
}
}
System.out.println(result); for (int h = k-1; h > 0; h--) {
result = persons.get(index--).name;
for (int j = 1; j < rowPeo; j++) {
if (j%2==1) {
result=persons.get(index--).name+" "+result;
}else {
result=result+" "+persons.get(index--).name;
}
}
System.out.println(result);
}
}
} //创建一个person类 并且将所有的人按照身高排序(从小到大)
class Person implements Comparator {
String name;
int height; @Override
public int compare(Object o1, Object o2) {
Person p1 = (Person)o1;
Person p2 = (Person)o2;
return p1.height-p2.height;
}
}
从这个实例介绍comparator和comparable的区别
首先给出两者的区别:
1:Comparable 自然排序。(实体类实现)
2:Comparator 是定制排序。(无法修改实体类时,直接在调用方创建)
对于一些普通的数据类型(比如 String, Integer, Double…),它们默认实现了Comparable 接口,实现了 compareTo 方法,我们可以直接使用。可以直接通过Collections.Sort() 或者通过 Arrars.sort()实现对数组的排序。
而对于一些自定义类,它们可能在不同情况下需要实现不同的比较策略,我们可以新创建 Comparator 接口,然后使用特定的 Comparator 实现进行比较。
Comparable 自然排序
Comparable 在 java.lang 包下,是一个接口,内部只有一个方法 compareTo():
Modifier and Type | Method and Description |
---|---|
int |
compareTo(T o)
Compares this object with the specified object for order.
|
阅读API知道在comparable中只有一个方法 compareTo()
compareTo 方法的返回值有三种情况:
- e1.compareTo(e2) > 0 即 e1 > e2
- e1.compareTo(e2) = 0 即 e1 = e2
- e1.compareTo(e2) < 0 即 e1 < e2
实际上所有实现了 Comparable 接口的 Java 核心类的结果都和 equlas 方法保持一致。
实现了 Comparable 接口的 List 或则数组可以使用Collections.sort()
或者Arrays.sort()
方法进行排序。 API中有两点要求:
1.由于 null 不是一个类,也不是一个对象,因此在重写 compareTo 方法时应该注意 e.compareTo(null) 的情况,即使 e.equals(null) 返回 false,compareTo 方法也应该主动抛出一个空指针异常 NullPointerException。
2.Comparable 实现类重写 compareTo 方法时一般要求 e1.compareTo(e2) == 0 的结果要和 e1.equals(e2) 一致。这样将来使用 SortedSet 等根据类的自然排序进行排序的集合容器时可以保证保存的数据的顺序和想象中一致。(如果这个条件不满足,则必须使用comparator接口)
Comparator 定制排序
Comparator 在 java.util 包下,也是一个接口,
Modifier and Type | Method and Description |
---|---|
int |
compare(T o1, T o2)
Compares its two arguments for order.
|
boolean |
equals(Object obj)
Indicates whether some other object is "equal to" this comparator.
|
Comparator 是在外部制定排序规则,然后作为排序策略参数传递给某些类,若一个类要实现Comparator接口:
它一定要实现compareTo(T o1, T o2) 函数,但可以不实现 equals(Object obj) 函数。
为什么可以不实现 equals(Object obj) 函数呢? 因为任何类,默认都是已经实现了equals(Object obj)的。
Java中的一切类都是继承于java.lang.Object,在Object.java中实现了equals(Object obj)函数;所以,其它所有的类也相当于都实现了该函数。
使用方式主要分三步:
- 创建一个 Comparator 接口的实现类,并赋值给一个对象 将 Comparator 对象作为参数传递给 排序类的某个方法
- 在 compare 方法中针对自定义类写排序规则
- 向排序类中添加 compare 方法中使用的自定义类
上面的例子中,自定义通过height来自定义排序。 下面借鉴一位博主的代码 http://www.cnblogs.com/skywang12345/p/3324788.html
import java.util.*;
import java.lang.Comparable; /**
* @desc "Comparator"和“Comparable”的比较程序。
* (01) "Comparable"
* 它是一个排序接口,只包含一个函数compareTo()。
* 一个类实现了Comparable接口,就意味着“该类本身支持排序”,它可以直接通过Arrays.sort() 或 Collections.sort()进行排序。
* (02) "Comparator"
* 它是一个比较器接口,包括两个函数:compare() 和 equals()。
* 一个类实现了Comparator接口,那么它就是一个“比较器”。其它的类,可以根据该比较器去排序。
*
* 综上所述:Comparable是内部比较器,而Comparator是外部比较器。
* 一个类本身实现了Comparable比较器,就意味着它本身支持排序;若它本身没实现Comparable,也可以通过外部比较器Comparator进行排序。
*/
public class CompareComparatorAndComparableTest{ public static void main(String[] args) {
// 新建ArrayList(动态数组)
ArrayList<Person> list = new ArrayList<Person>();
// 添加对象到ArrayList中
list.add(new Person("ccc", 20));
list.add(new Person("AAA", 30));
list.add(new Person("bbb", 10));
list.add(new Person("ddd", 40)); // 打印list的原始序列
System.out.printf("Original sort, list:%s\n", list); // 对list进行排序
// 这里会根据“Person实现的Comparable<String>接口”进行排序,即会根据“name”进行排序
Collections.sort(list);
System.out.printf("Name sort, list:%s\n", list); // 通过“比较器(AscAgeComparator)”,对list进行排序
// AscAgeComparator的排序方式是:根据“age”的升序排序
Collections.sort(list, new AscAgeComparator());
System.out.printf("Asc(age) sort, list:%s\n", list); // 通过“比较器(DescAgeComparator)”,对list进行排序
// DescAgeComparator的排序方式是:根据“age”的降序排序
Collections.sort(list, new DescAgeComparator());
System.out.printf("Desc(age) sort, list:%s\n", list); // 判断两个person是否相等
testEquals();
} /**
* @desc 测试两个Person比较是否相等。
* 由于Person实现了equals()函数:若两person的age、name都相等,则认为这两个person相等。
* 所以,这里的p1和p2相等。
*
* TODO:若去掉Person中的equals()函数,则p1不等于p2
*/
private static void testEquals() {
Person p1 = new Person("eee", 100);
Person p2 = new Person("eee", 100);
if (p1.equals(p2)) {
System.out.printf("%s EQUAL %s\n", p1, p2);
} else {
System.out.printf("%s NOT EQUAL %s\n", p1, p2);
}
} /**
* @desc Person类。
* Person实现了Comparable接口,这意味着Person本身支持排序
*/
private static class Person implements Comparable<Person>{
int age;
String name; public Person(String name, int age) {
this.name = name;
this.age = age;
} public String getName() {
return name;
} public int getAge() {
return age;
} public String toString() {
return name + " - " +age;
} /**
* 比较两个Person是否相等:若它们的name和age都相等,则认为它们相等
*/
boolean equals(Person person) {
if (this.age == person.age && this.name == person.name)
return true;
return false;
} /**
* @desc 实现 “Comparable<String>” 的接口,即重写compareTo<T t>函数。
* 这里是通过“person的名字”进行比较的
*/
@Override
public int compareTo(Person person) {
return name.compareTo(person.name);
//return this.name - person.name;
}
} /**
* @desc AscAgeComparator比较器
* 它是“Person的age的升序比较器”
*/
private static class AscAgeComparator implements Comparator<Person> { @Override
public int compare(Person p1, Person p2) {
return p1.getAge() - p2.getAge();
}
} /**
* @desc DescAgeComparator比较器
* 它是“Person的age的升序比较器”
*/
private static class DescAgeComparator implements Comparator<Person> { @Override
public int compare(Person p1, Person p2) {
return p2.getAge() - p1.getAge();
}
} }
下面对这个程序进行说明。
a) Person类定义。如下:
private static class Person implements Comparable<Person>{
int age;
String name; ... /**
* @desc 实现 “Comparable<String>” 的接口,即重写compareTo<T t>函数。
* 这里是通过“person的名字”进行比较的
*/
@Override
public int compareTo(Person person) {
return name.compareTo(person.name);
//return this.name - person.name;
}
}
说明:
(01) Person类代表一个人,Persong类中有两个属性:age(年纪) 和 name“人名”。
(02) Person类实现了Comparable接口,因此它能被排序。
b) 在main()中,我们创建了Person的List数组(list)。如下:
// 新建ArrayList(动态数组)
ArrayList<Person> list = new ArrayList<Person>();
// 添加对象到ArrayList中
list.add(new Person("ccc", 20));
list.add(new Person("AAA", 30));
list.add(new Person("bbb", 10));
list.add(new Person("ddd", 40));
c) 然后,我们通过Collections的sort()函数,对list进行排序。
由于Person实现了Comparable接口,因此通过sort()排序时,会根据Person支持的排序方式,即 compareTo(Person person) 所定义的规则进行排序。如下:
// 对list进行排序
// 这里会根据“Person实现的Comparable<String>接口”进行排序,即会根据“name”进行排序
Collections.sort(list);
System.out.printf("Name sort, list:%s\n", list);
e) 对比Comparable和Comparator
我们定义了两个比较器 AscAgeComparator 和 DescAgeComparator,来分别对Person进行 升序 和 降低 排序。
e.1) AscAgeComparator比较器
它是将Person按照age进行升序排序。代码如下:
/**
* @desc AscAgeComparator比较器
* 它是“Person的age的升序比较器”
*/
private static class AscAgeComparator implements Comparator<Person> { @Override
public int compare(Person p1, Person p2) {
return p1.getAge() - p2.getAge();
}
}
e.2) DescAgeComparator比较器
它是将Person按照age进行降序排序。代码如下:
/**
* @desc DescAgeComparator比较器
* 它是“Person的age的升序比较器”
*/
private static class DescAgeComparator implements Comparator<Person> { @Override
public int compare(Person p1, Person p2) {
return p2.getAge() - p1.getAge();
}
}
PAT——1055. 集体照 (比较comparable和comparator的区别)的更多相关文章
- Java中Comparable和Comparator接口区别分析
Java中Comparable和Comparator接口区别分析 来源:码农网 | 时间:2015-03-16 10:25:20 | 阅读数:8902 [导读] 本文要来详细分析一下Java中Comp ...
- PAT 1055 集体照 (25)(STL-list+代码)
1055 集体照 (25)(25 分)提问 拍集体照时队形很重要,这里对给定的N个人K排的队形设计排队规则如下: 每排人数为N/K(向下取整),多出来的人全部站在最后一排: 后排所有人的个子都不比前排 ...
- Java中Comparable与Comparator的区别
相同 Comparable和Comparator都是用来实现对象的比较.排序 要想对象比较.排序,都需要实现Comparable或Comparator接口 Comparable和Comparator都 ...
- Comparable和Comparator的区别
Comparable Comparable可以认为是一个内比较器,实现了Comparable接口的类有一个特点,就是这些类是可以和自己比较的,至于具体和另一个实现了Comparable接口的类如何比较 ...
- Comparable和Comparator的区别&Collections.sort的两种用法
在Java集合的学习中,我们明白了: 看到tree,可以按顺序进行排列,就要想到两个接口.Comparable(集合中元素实现这个接口,元素自身具备可比性),Comparator(比较器,传入容器构造 ...
- 面试----java基础集合---------------------comparable和comparator 的区别
comparable接口 是主要是用来自定义类存储在主要是TreeSet,TreeMap(键)集合中存储时,自定通过实现这种接口得到自然排序的功能. comparator 接口 是主要是用来 ...
- 浅谈Comparable与Comparator的区别
平时进行自定义排序一直使用实现Comparable接口,一段时间后操作的时候居然发现有了个Comparator接口 上网差了些资料,总结笔记一下. 基本原理就是比较,底层是二叉树 比如是3,6,5,1 ...
- 你能说说Java中Comparable和Comparator的区别吗
之前面试中被问到这个问题,当时不屑(会)回答,下来特意查了查,整理如下. Java 中为我们提供了两种比较机制:Comparable 和 Comparator,二者都是用来实现对象的比较.排序. 下面 ...
- PAT——1055. 集体照
拍集体照时队形很重要,这里对给定的N个人K排的队形设计排队规则如下: 每排人数为N/K(向下取整),多出来的人全部站在最后一排: 后排所有人的个子都不比前排任何人矮: 每排中最高者站中间(中间位置为m ...
随机推荐
- MyBatis_动态代理
一.项目结构 二.代码实现 import java.util.List; import java.util.Map; import com.jmu.bean.Student; public inter ...
- git的问题(error: object file .git/objects/* is empty...)的解决方案及对git版本库文件的了解
由于操作不当,导致git版本库出了大问题,如下所示: error: object file .git/objects/8b/61d0135d3195966b443f6c73fb68466264c68e ...
- TCP keepalive长连接心跳保活
比如:客户端与服务端进行握手时,经常无法握手成功,收不到回复: 需要建立保活机制. 1. 服务端Linux服务器新增系统内核参数配置. 在/etc/sysctl.conf文件中再添加如: #允许的持续 ...
- <Android 基础(十九)> CoordinatorLayout
介绍 CoordinatorLayout,中文翻译,协调布局,顾名思义,此布局中的子View之间,子View与父布局之间应该是可以协调工作的,如何协调,Behavior. 今天看下Android St ...
- DUANG~ 万网轻云服务器,大促狂欢,不仅仅免单!
DUANG~ 万网轻云服务器,大促狂欢,不仅仅免单! 当老板第一次知道我们要做活动的时候,其实是拒绝的.DUANG~ 打折.降价.挥泪甩卖…太俗套.客户看到一定骂我们,根本没有诚意. 所以轻云大促 ...
- MySQL数据库备份与还原
备份数据库 1.使用mysqldump命令备份 备份一个数据库:mysqldump -u 用户名 -p密码 数据库名 [表名1,表名2...]>备份文件路径及名字.sql 如 ...
- select下拉框默认不能选择第一个选项的问题
如题,现在有个js的功能:用户选择下拉框的同时,把选择的下拉框显示出来.同时选择的不能有重复的.刚开始 使用的是 select的onchange事件: $("#liveType") ...
- Android学习——Service(二)
今天来介绍Service的第二种使用方式,Bind方式 Bind方式启动服务 Bind方式和Start方式启动很类似,都是通过Intent来启动,不同的是,Bind方式需要传入三个参数,如下: Int ...
- angularJS articles and resources
http://antjanus.com/blog/web-development-tutorials/front-end-development/comprehensive-beginner-guid ...
- yii 只查询指定字段
$cri = new CDBcriteria(); $cri->addCondition( ' hid = '.$hid.' ' ); $cri->select = 'id,propert ...