1028 人口普查 (20分)
某城镇进行人口普查,得到了全体居民的生日。现请你写个程序,找出镇上最年长和最年轻的人。
这里确保每个输入的日期都是合法的,但不一定是合理的——假设已知镇上没有超过 200 岁的老人,而今天是 2014 年 9 月 6 日,所以超过 200 岁的生日和未出生的生日都是不合理的,应该被过滤掉。
输入格式:
输入在第一行给出正整数 N,取值在(0,10^5 ];随后 N 行,每行给出 1 个人的姓名(由不超过 5 个英文字母组成的字符串)、以及按 yyyy/mm/dd(即年/月/日)格式给出的生日。题目保证最年长和最年轻的人没有并列。
输出格式:
在一行中顺序输出有效生日的个数、最年长人和最年轻人的姓名,其间以空格分隔。
输入样例:
5
John 2001/05/12
Tom 1814/09/06
Ann 2121/01/30
James 1814/09/05
Steve 1967/11/20
输出样例:
3 Tom John
解题思路:
此题题意也很容易理解,只需找出在时间段[1814/09/06-2014/09/06]之间的最晚和最早时间。
如何判断时间段是否符合,以及求最大和最小。我刚开始第一想法就是用TreeMap的有序性来排序,后测试发现最后一个测试点运行超时。见下侧代码实现一。
后来考虑可能是TreeMap消耗资源过多,占用内存过大,考虑不存储所有数据,只存储最大最小,动态比较给最大最小变量赋值。发现还是最后一个测试点运行超时。见下侧代码实现二。
又考虑String的compareTo()方法效率低,将其转换为int 类型直接比较。还是最后一个测试点运行超时。 见下侧代码实现三。
坑一: 刚开始是以为考察重点是求200年前具体年月日,后通过观察测试用例发现不是这样。
坑二: 若所有数据都不符合规则,则应只输出 0
坑三: 若数据只有一条,年纪最大和最小都应输出同一个人名,即打印两个相同的名字。
最后一个测试点未过,运行超时,得分16。试了好几种方法还是运行超时,心态不好了。求大佬解答。
代码实现一:
利用TreeMap的有序性来排序
import java.util.Collection; import java.util.Map; import java.util.Scanner; import java.util.TreeMap;
public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int number = sc.nextInt(); sc.nextLine(); String max = "2014/09/06"; String min = "1814/09/06"; Map<String,String> map = new TreeMap<>(); for(int x = 0; x < number; x++){ String[] data = sc.nextLine().split(" "); if(data[1].compareTo(min) >= 0 && data[1].compareTo(max) <= 0 ){ map.put(data[1],data[0]); } } if(map.size() == 0){ System.out.print("0"); }else{ System.out.print(map.size() + " "); Object[] values = map.values().toArray(); System.out.print(values[0] + " "); System.out.print(values[values.length-1]); } } }
|
代码实现二:
动态比较给最大最小变量赋值
import java.util.Map; import java.util.Scanner; import java.util.TreeMap;
public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int number = sc.nextInt(); sc.nextLine(); String max = "1814/09/06"; String min = "2014/09/06"; int count = 0; String maxName = ""; String minName = ""; for(int x = 0; x < number; x++){ String[] data = sc.nextLine().split(" "); if(data[1].compareTo("1814/09/06") >= 0 && data[1].compareTo("2014/09/06") <= 0 ){ count++; if(data[1].compareTo(max) >= 0){ max = data[1]; maxName = data[0]; } if(data[1].compareTo(min) <= 0){ min = data[1]; minName = data[0]; } } } if(count == 0){ System.out.print("0"); }else{ System.out.print(count + " "); System.out.print(minName + " "); System.out.print(maxName ); } } }
|
代码实现三:
动态比较给最大最小变量赋值
import java.util.Scanner;
public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int number = sc.nextInt(); sc.nextLine(); int max = 18140906; int min = 20140906; int count = 0; String maxName = ""; String minName = ""; for(int x = 0; x < number; x++){ String[] data = sc.nextLine().split(" "); int date = Integer.parseInt(data[1].replaceAll("/","")); if(date >= 18140906 && date <= 20140906){ count++; if(date >= max){ max = date; maxName = data[0]; } if(date <= min){ min = date; minName = data[0]; } } } if(count == 0){ System.out.print("0"); }else{ System.out.print(count + " "); System.out.print(minName + " "); System.out.print(maxName ); } } }
|
最新进度:
牛客网相同的代码所有测试点都通过了,在PAT中就不行。
暂且这样吧,理解题目的考察点。
在这个问题上折腾了快一天了,就不再耗费时间了。