PAT 乙级 1028 人口普查 Java 解决

写在最前:欢迎批评,欢迎任意地方的指正,用你们的优秀的java代码砸死我吧!!

问题——————

某城镇进行人口普查,得到了全体居民的生日。现请你写个程序,找出镇上最年长和最年轻的人。

这里确保每个输入的日期都是合法的,但不一定是合理的——假设已知镇上没有超过 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

解题思路:

讲道理,我觉得我这个是全网最快的java解决这道题的解法了,(不相信的话看一下思路和代码,你会同意的)但是还是无法通过 最后一个检查点,出于好奇就使用了网上通过的c++的代码去试了一下,发现平常检查点2到3ms解决的问题到了最后一个点要50+ms,不禁陷入沉思,这让Java怎么活?Java正常检查点就得70+ms左右。

不抱怨了,既然选择了Java就要一条路走下去,来看思路:题目说处理生日和人名,日期是特定格式的字符串,然后有两个关键边界点 2014/09/06 和 1814/09/06 ,对于这两个日期来说,题目描述的并不是很清楚开闭区间,但是根据给出的样例暂且得出结论,两个日期的生日都是有效的,必须大于或小于才是无效。从这里开始,正常思路是对日期进行比对是否有效然后存入一个集合中,进行排序或者别的方法遍历得到最大最小值。但是可以换个思路来想,日期比对我看网上有分成数字比对的,有格式化成日期(Date)对象比对的,但是还没有发现直接使用String进行比对的,这种东西直接通过String比对是可以的,String默认比较方法是每个字符的ascii码值,对于日期来说,一定符合:a字符串小于b字符串那么a日期一定小于b日期,即a比b老,根据这个结论,直接进行字符串比对,不需要任何的变换。然后就是存储的方式,刚开始想得方法是使用Map集合存储,然后进行值排序(吧map变成entry的list,然后新建比较器对每个元素的值进行比较),后来看到了题目中的“题目保证最年长和最年轻的人没有并列”  ,那就好说了,把日期这个字符串当成map中的键,并且不怕有元素覆盖,本身题目只需要最大和最小的,而最大最小的又不怕覆盖,所以顺理成章地直接使用treeMap进行存储,根据treemap的自动排序存储,转化成entry的list直接输出第一个元素和最后一个元素的值,即名字,并且输出每次判断是否有效时累加的一个计数值即可。但是,依旧无法通过最后一个检查点。。

希望大佬写出来Java的ac代码让小弟我看看,感激不尽

package not.die.in.here;

import java.io.*;
import java.util.*;
import java.util.Map.Entry;

public class _1028_PeopleCheck{
	public static boolean isValid(String birthday) {
		if(birthday.compareTo("1814/09/06") <= -1 || birthday.compareTo("2014/09/06")  >= 1)//新建一个判断日期是否有效的函数,这两个日期是有效的
			return false;
		return true;
	}
	
	public static void main(String[] args) throws NumberFormatException, IOException {
		BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));//buffer加快读取速度
		int n = Integer.parseInt(bf.readLine());//读取人数
		String[] buf = null;
		String[] buf2 = new String[n];
		Map<String,String> man = new TreeMap<>(); //存放人的数据
		int count = 0;
		for(int i=0;i<n;i++) {
			buf2[i] = bf.readLine();//不打断数据读取会不会更快一些呢...
		}
		bf.close();
		for(int i=0;i<n;i++) {
			buf = buf2[i].split(" ");
			if(isValid(buf[1])) {//如果有效就计数并且添加进map,吧生日当成是键
				count++;
				man.put(buf[1],buf[0]);
			}
		}
		List<Entry<String,String>> entry = new ArrayList<Entry<String, String>>(man.entrySet());//转化成list便于直接输出第一项和最后一项
		if(entry.size()>0)//如果有效生日个数大于0输出结果
			System.out.println(count+" "
										+entry.get(0).getValue()+" "
										+entry.get(entry.size()-1).getValue());
		else {//没有有效的生日则直接输出0
			System.out.println(0);
		}
	}
}

提交截图:

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值