拍集体照时队形很重要,这里对给定的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)函数;所以,其它所有的类也相当于都实现了该函数。

使用方式主要分三步:

  1. 创建一个 Comparator 接口的实现类,并赋值给一个对象 将 Comparator 对象作为参数传递给 排序类的某个方法
  2. 在 compare 方法中针对自定义类写排序规则
  3. 向排序类中添加 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的区别)的更多相关文章

  1. Java中Comparable和Comparator接口区别分析

    Java中Comparable和Comparator接口区别分析 来源:码农网 | 时间:2015-03-16 10:25:20 | 阅读数:8902 [导读] 本文要来详细分析一下Java中Comp ...

  2. PAT 1055 集体照 (25)(STL-list+代码)

    1055 集体照 (25)(25 分)提问 拍集体照时队形很重要,这里对给定的N个人K排的队形设计排队规则如下: 每排人数为N/K(向下取整),多出来的人全部站在最后一排: 后排所有人的个子都不比前排 ...

  3. Java中Comparable与Comparator的区别

    相同 Comparable和Comparator都是用来实现对象的比较.排序 要想对象比较.排序,都需要实现Comparable或Comparator接口 Comparable和Comparator都 ...

  4. Comparable和Comparator的区别

    Comparable Comparable可以认为是一个内比较器,实现了Comparable接口的类有一个特点,就是这些类是可以和自己比较的,至于具体和另一个实现了Comparable接口的类如何比较 ...

  5. Comparable和Comparator的区别&Collections.sort的两种用法

    在Java集合的学习中,我们明白了: 看到tree,可以按顺序进行排列,就要想到两个接口.Comparable(集合中元素实现这个接口,元素自身具备可比性),Comparator(比较器,传入容器构造 ...

  6. 面试----java基础集合---------------------comparable和comparator 的区别

    comparable接口     是主要是用来自定义类存储在主要是TreeSet,TreeMap(键)集合中存储时,自定通过实现这种接口得到自然排序的功能. comparator 接口  是主要是用来 ...

  7. 浅谈Comparable与Comparator的区别

    平时进行自定义排序一直使用实现Comparable接口,一段时间后操作的时候居然发现有了个Comparator接口 上网差了些资料,总结笔记一下. 基本原理就是比较,底层是二叉树 比如是3,6,5,1 ...

  8. 你能说说Java中Comparable和Comparator的区别吗

    之前面试中被问到这个问题,当时不屑(会)回答,下来特意查了查,整理如下. Java 中为我们提供了两种比较机制:Comparable 和 Comparator,二者都是用来实现对象的比较.排序. 下面 ...

  9. PAT——1055. 集体照

    拍集体照时队形很重要,这里对给定的N个人K排的队形设计排队规则如下: 每排人数为N/K(向下取整),多出来的人全部站在最后一排: 后排所有人的个子都不比前排任何人矮: 每排中最高者站中间(中间位置为m ...

随机推荐

  1. Java基础(十一)集合框架

    一.集合框架 1.集合框架定义 集合框架是一个用来代表和操纵集合的统一架构.所有的集合框架都包含如下内容: 接口:是代表集合的抽象数据类型.接口允许集合独立操纵其代表的细节.在面向对象的语言,接口通常 ...

  2. Javaweb之EL表达式

    1.EL表达式简介 EL全名为Expression Language.EL的主要作用为: 获取数据:EL表达式主要用于替换jsp页面中的脚本表达式,以从各种类型的web域中检索java对象,获取数据. ...

  3. Java 带缓冲的字节流和字符流

    输入流就是文件从硬盘到内存的中间媒介,那么输出流就是文件从内存到硬盘的中间媒介.首先来看看FileOutputStream的继承了哪些类, java.lang.Object java.io.Outpu ...

  4. flask-login2的简单使用

    #coding:utf8 from flask import Flask, render_template, request, redirect, url_for, flash, abort from ...

  5. Hibernate 函数 ,子查询 和原生SQL查询

    一. 函数 聚合函数:count(),avg(),sum(),min(),max() 例:(1)查询Dept表中的所有的记录条数. String hql=" select count(*) ...

  6. 数组之reduce()和reduceRight()

    1.reduce()和reduceRight()方法使用指定的函数将数组元素进行组合,生成单个值. reduce()可以传入两个参数,第一个是执行化简操作的函数.同样这个函数可以有参数,第一个参数代表 ...

  7. HTML5 localstorage和session操作

    setStorage={ getLocal : function(key){ //获得localStorage里面的值 var storage = window.localStorage; if(st ...

  8. 小白学习css记录

    一.复习 什么是CSS? 层叠样式表 -层叠样式只会被覆盖而不会被替代 CSS的使用方式 style属性---> <h1 style="css属性"></h ...

  9. Caffe&Torch&Theano&TensorFlow

    https://www.youtube.com/watch?v=Qynt-TxAPOs&index=12&list=PL16j5WbGpaM0_Tj8CRmurZ8Kk1gEBc7fg ...

  10. hdu 4513 吉哥系列故事——完美队形II (manachar算法)

    吉哥系列故事——完美队形II Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) P ...