题目描述
考勤记录是分析和考核职工工作时间利用情况的原始依据,也是计算职工工资的原始依据,为了正确地计算职工工资和监督工资基金使用情况,公司决定对员工的手机打卡记录进行异常排查。如果出现以下两种情况,则认为打卡异常:实际设备号与注册设备号不一样 或者,同一个员工的两个打卡记录的时间小于60分钟并且打卡距离超过5km。 给定打卡记录的字符串数组 clockRecords(每个打卡记录组成为:工号;时间(分钟);打卡距离(km);实际设备号;注册设备号),返回其中异常的打卡记录(按输入顺序输出)
输入描述
第一行输入为N,表示打卡记录数;
之后的N行为打卡记录,每一行为一条打卡记录。
备注
clockRecords长度 ≤ 1000- clockRecords[i] 格式:
{id},{time},{distance},{actualDeviceNumber},{registeredDeviceNumber}id由6位数字组成 time由整数组成,范围为0 ~ 1000distance由整数组成,范围为0 ~100actualDeviceNumber与registeredDeviceNumber由四位大写字母组成.
输出描述
输出异常的打卡记录
用例1
输入
2
100000,10,1,ABCD,ABCD
100000,50,10,ABCD,ABCD
输出
100000,10,1,ABCD,ABCD;100000,50,10,ABCD,ABCD
用例2
输入
2
100000,10,1,ABCD,ABCD
100001,80,10,ABCE,ABCE
输出
null
用例3
输入
输出
100000,80,10,ABCE,ABCD
思路:
1. 对于每一条打卡记录,实际设备号与注册设备号不一样则视为异常打卡
2.对于两个打卡记录比较,注意:正常的打卡记录最多只能有两条!因此对于同一个员工号,所有记录都要跟自己的第一条记录比较。
3.使用hashmap 存储每一个员工的打卡记录列表,以及输入顺序。
4.结果一定要去重,使用set保存结果。最后按照输入顺序 打印异常的打卡记录
package 模拟考试2;
import java.util.*;
import java.util.stream.Collectors;
//异常的打卡记录
/**
1. 实际设备号与注册设备号不一样
2.同一个员工的两个打卡记录的时间小于60分钟并且打卡距离超过5km。
即同一员工的两次相近的打卡记录 时间小于60分钟、并且两次打卡的位置的距离超过5km。 如果超过2条打卡记录,所有记录都跟第一条进行比较!!!因为正常打卡只有2条
3.防止重复记录,使用hashset
4.返回其中异常的打卡记录(按输入顺序输出)
*/
public class Solution109 {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n=Integer.parseInt(in.nextLine());
HashMap<Integer, ArrayList<Emp>> map = new HashMap<>(); // {id,Emp}
for (int i=0;i<n;i++){
String[] str = in.nextLine().split(",");
int id = Integer.parseInt(str[0]);
int time = Integer.parseInt(str[1]);
int distance = Integer.parseInt(str[2]);
String actualDeviceNumber= str[3];
String registeredDeviceNumber= str[4];
Emp emp=new Emp(id,time,distance,actualDeviceNumber,registeredDeviceNumber,i+1);
ArrayList<Emp> list = map.getOrDefault(id, new ArrayList<>());
list.add(emp);
map.put(id,list);
}
HashSet<Emp> set=new HashSet<>();
for (Map.Entry<Integer, ArrayList<Emp>> entry : map.entrySet()) {
ArrayList<Emp> list = entry.getValue();
Emp first = list.get(0);
//如果只有一次打卡记录,则只判断打卡设备和注册设备是否一致
if (!first.actualDeviceNumber.equals(first.registeredDeviceNumber)){
set.add(list.get(0));
}
for (int i=1;i<list.size();i++){
Emp emp = list.get(i);
//当前记录的打卡设备和注册设备是否一致
if (!emp.actualDeviceNumber.equals(emp.registeredDeviceNumber)){
set.add(emp);
}
//全部跟第一次记录比较
if ( Math.abs(emp.time-first.time)<60&& Math.abs(emp.distance-first.distance)>5){
set.add(first);
set.add(emp);
}
}
}
if (set.isEmpty()){
System.out.println("null");
return;
}
List<Emp> collect = set.stream().sorted(Comparator.comparingInt(o -> o.pos)).collect(Collectors.toList());
StringBuilder builder = new StringBuilder();
for (Emp emp : collect) {
String a=emp.id+","+emp.time+","+emp.distance+","+emp.actualDeviceNumber+","+emp.registeredDeviceNumber+";";
builder.append(a);
}
//去掉最后一个分号
System.out.println(builder.deleteCharAt(builder.length() - 1));
}
//考勤信息
static class Emp{
int id;
int time;
int distance;
String actualDeviceNumber;
String registeredDeviceNumber;
int pos; //输入顺序
public Emp( int id, int time,int distance,String actualDeviceNumber,String registeredDeviceNumber,int pos){
this.id=id;
this.time=time;
this.distance=distance;
this.actualDeviceNumber=actualDeviceNumber;
this.registeredDeviceNumber=registeredDeviceNumber;
this.pos=pos;
}
}
}
2036

被折叠的 条评论
为什么被折叠?



