题目描述:
终端铲=产品的儿童电话手表具有防骚扰特性,对电话呼入按如下规则处理:
如果来电号码在白名单中,则电话要接通。否则电话自动拒接。
先给定一组电话呼入和白名单的操作记录,格式为:
C 13300000000 表示一条电话呼入记录。
W 13144444444 表示添加一个号码到白名单中;
W 03712832* 表示以03712832开头的号码都为白名单(*表示通配符,仅在结尾)。
请按照给定的过程记录,分别统计每个呼入号码的接通和拒接次数;
每个号码的统计记录的格式如: 13144444444 1 3,以单个空格隔开,表示号码13144444444 接通1次,拒接3次。
统计记录的输出顺序;按照给定记录中号码的首次呼入出现的先后顺序。
解题要求:
时间限制:1000ms, 内存限制:256M
输入:
第一行正数n,表示共有n条电话呼入和白名单操作记录,取值范围为[1,3000].
随后n行时电话呼入和白名单操作记录。
注:用例保证,号码仅为数字,长度范围为[3,11]
输出:
每一行一个字符串,代表一个呼入号码的统计记录
样例:
输入样例1:
7
C 13300000000
W 13144444444
C 13144444444
C 03712832444
C 03712832233
W 03712832*
C 03712832444
输出样例1:
13300000000 0 1
13144444444 1 0
03712832444 1 1
03712832233 0 1
提示样例1
13300000000 呼入了1次,不在白名单中,接通0次,拒接1次。
13144444444 呼入前已加入报名单,接通一次,拒接0次
白名单03712832*加入前,03712832233和03712832444都被拒接了,加入后03712832444接通一次。
注意:需要按号码出现的顺序输入统计记录。
C++解答:
解题思路:
1、定义一个string类型的队列,保存呼入号码出现的顺序,出现过的只保留1次
定义一个数组存放白名单号码
定义一个unordered_map<string, pair<int, int>>,存放结果,最后需要转为字符串
2、判断是否在白名单内,在接通+1,不在拒接+1
3、W操作,则加入白名单列表中
代码如下:
#include <iostream>
#include <vector>
#include <string>
#include <queue>
#include <unordered_map>
using namespace std;
class Solution {
public:
vector<string> getPhoneBlockTimes(vector<pair<char, string>> phoneRecords)
{
int i = 0;
for(const auto &[opt, phoneNum] : phoneRecords) {
if(opt == 'C') {
if(ans.count(phoneNum) == 0) {
phoneFifo.push(phoneNum);
}
if(isInWhiteList(phoneNum)) {
ans[phoneNum].first ++;
} else {
ans[phoneNum].second ++;
}
} else if(opt == 'W') {
whiteList.push_back(phoneNum);
}
}
i = 0;
vector<string> result;
while(!phoneFifo.empty()) {
string s = phoneFifo.front();
phoneFifo.pop();
result.push_back(s + " " + to_string(ans[s].first) + " " +to_string(ans[s].second));
}
return result;
}
private:
queue<string> phoneFifo;
vector<string> whiteList;
unordered_map<string, pair<int, int>> ans;
bool isInWhiteList(const string phoneNum) {
string s = phoneNum;
for(auto s1 : whiteList) {
int pos = 0;
pos = s1.find('*');
if(pos != 0) {
if(s1.substr(0, pos) == s.substr(0, pos)) {
return true;
} else {
continue;
}
} else {
if(s == s1) {
return true;
} else {
continue;
}
}
}
return false;
}
};
int main()
{
int count;
cin >> count;
vector<pair<char, string>> phoneRecords;
for(int i = 0; i < count; i++) {
char oper;
string phoneNum;
cin >> oper >> phoneNum;
phoneRecords.push_back(make_pair(oper, phoneNum));
}
#if 0
for(auto it : phoneRecords) {
cout << it.first << " " << it.second << endl;;
}
#endif
Solution solu;
vector<string> result = solu.getPhoneBlockTimes(phoneRecords);
for(auto s : result) {
cout << s << endl;
}
return 0;
}
python解答:
思路: 利用dict的defaultdict方法,创建一个可以赋值的dict
ans = defaultdict(lambda : [0, 0]) (该操作需要引入from collections import defaultdict)
具体代码如下:
#!/usr/bin/env python
# coding=utf-8
from collections import defaultdict
class Solution:
def getPhoneRecords(self, phoneRecords):
set1 = set()
set2 = set()
ans = defaultdict(lambda : [0, 0])
for phoneRecord in phoneRecords:
if phoneRecord[0] == 'W':
if phoneRecord[1][-1] == '*':
set2.add(phoneRecord[1][:-1])
else:
set1.add(phoneRecord[1])
else:
if phoneRecord[1] in set1 or any(phoneRecord[1].startswith(x) for x in set2):
ans[phoneRecord[1]][0] += 1
else:
ans[phoneRecord[1]][1] += 1
return ['{0} {1} {2}'.format(k, v[0], v[1]) for k, v in ans.items()]
if __name__ == "__main__":
count = int(input().strip())
phoneRecords = [input().strip().split() for _ in range(count)]
function = Solution()
result = function.getPhoneRecords(phoneRecords);
for s in result :
print(s)
any函数,用于给定的可迭代参数是否全部为False,则返回False,如果一个为True,则返回True
startswith(x) 用于检查已给字符串是否以指定的前缀开头。