题目链接:https://leetcode-cn.com/problems/alert-using-same-key-card-three-or-more-times-in-a-one-hour-period/
题意:
力扣公司的员工都使用员工卡来开办公室的门。每当一个员工使用一次他的员工卡,安保系统会记录下员工的名字和使用时间。如果一个员工在一小时时间内使用员工卡的次数大于等于三次,这个系统会自动发布一个 警告 。
给你字符串数组 keyName 和 keyTime ,其中 [keyName[i], keyTime[i]] 对应一个人的名字和他在 某一天 内使用员工卡的时间。
使用时间的格式是 24小时制 ,形如 "HH:MM" ,比方说 "23:51" 和 "09:49" 。
请你返回去重后的收到系统警告的员工名字,将它们按 字典序升序 排序后返回。
请注意 "10:00" - "11:00" 视为一个小时时间范围内,而 "23:51" - "00:10" 不被视为一小时内,因为系统记录的是某一天内的使用情况。
方法:利用哈希表的性质,将用户的姓名和打卡时间的关系映射成哈希表,再者把时间从字符串转化成数字,利用滑动窗口寻找每个用户是否存在一小时内打卡次数满3次的情况。
bool cmp(int s1,int s2)
{
return s1<s2;
}
bool cmp1(string s1,string s2)
{
return s1<s2;
}
class Solution {
public:
vector<string> alertNames(vector<string>& keyName, vector<string>& keyTime) {
unordered_map<string,vector<int>> mp;//哈希表<key,value>等价于<姓名,打卡时间>
vector<string> name;
for(int i=0;i<keyName.size();i++)
{
int hour=(keyTime[i][0]-'0')*10+(keyTime[i][1]-'0');
int minute=(keyTime[i][3]-'0')*10+(keyTime[i][4]-'0');
mp[keyName[i]].emplace_back(hour*60+minute);
}
for(auto iter=mp.begin();iter!=mp.end();iter++)
{
sort((iter->second).begin(),(iter->second).end(),cmp);//按时间先后排序
if((iter->second).size()<3) continue;//打卡时刻小于3的话,就不需要看这个人的打卡时刻
int left=0,right=1,len = (iter->second).size(),cnt=0;//滑动窗口左侧坐标,滑动窗口右侧坐标,vector总长度,记录一小时内的打卡次数
int deadline = 60;//一小时=60分钟
int initialTime = ((iter->second)[left]);
while(right<len)//滑动窗口右侧坐标滑动到向量的最大长度结束
{
int thisTime = ((iter->second)[right]);
cnt++;//计数次数自加
if(thisTime-initialTime<=deadline)//计算时间差
{
if(cnt==2)//如果满足条件就把员工姓名放入向量中,并且退出此次滑动窗口滑动的过程
{
name.emplace_back(iter->first);
break;
}
}
while(thisTime-initialTime>deadline)//如果和起始时间相差超过1小时,就说明离得过远,窗口左侧坐标右移
{
left++;//滑动窗口左坐标右移
cnt--;//计数次数减一
initialTime = ((iter->second)[left]);//更新滑动窗口左侧对应的坐标
if(cnt==0) break;//cnt计数次数如果是0代表着滑动窗口左侧坐标等于右侧坐标,结束此层循环
}
right++;//滑动窗口右坐标右移
}
}
sort(name.begin(),name.end(),cmp1);
return name;
}
};