题目
You are given several logs that each log contains a unique id and timestamp. Timestamp is a string that has the following format: Year:Month:Day:Hour:Minute:Second
, for example, 2017:01:01:23:59:59
. All domains are zero-padded decimal numbers.
Design a log storage system to implement the following functions:
void Put(int id, string timestamp)
: Given a log's unique id and timestamp, store the log in your storage system.
int[] Retrieve(String start, String end, String granularity)
: Return the id of logs whose timestamps are within the range from start to end. Start and end all have the same format as timestamp. However, granularity means the time level for consideration. For example, start = "2017:01:01:23:59:59", end = "2017:01:02:23:59:59", granularity = "Day", it means that we need to find the logs within the range from Jan. 1st 2017 to Jan. 2nd 2017.
Example 1:
put(1, "2017:01:01:23:59:59"); put(2, "2017:01:01:22:59:59"); put(3, "2016:01:01:00:00:00"); retrieve("2016:01:01:01:01:01","2017:01:01:23:00:00","Year"); // return [1,2,3], because you need to return all logs within 2016 and 2017. retrieve("2016:01:01:01:01:01","2017:01:01:23:00:00","Hour"); // return [1,2], because you need to return all logs start from 2016:01:01:01 to 2017:01:01:23, where log 3 is left outside the range.
Note:
- There will be at most 300 operations of Put or Retrieve.
- Year ranges from [2000,2017]. Hour ranges from [00,23].
- Output for Retrieve has no order required.
输入一个id和timestamp,需要对其进行保存,故用map<int,string>保存即可,输出一个范围的id,并且会给定粒度,例如粒度是Year,则只看年份范围内的记录即可,如果粒度是Hour,则需要从年份一直到小时,省略分和秒的差异,并且起始和终止时间戳以完整的形式给出,由于是string类型,所以可以比较大小,故只需按照相应的粒度,对不考察的部分置为统一的值,例如'x',即可比较两条记录的大小,自然可以得到符合相应范围的记录,所以在输入时,对记录进行处理,保存它的所有粒度的形式,粒度为Second时,保存完整记录,粒度为Minute时,秒的部分置为"xx",其余部分正常保存,以此类推,对所有可能的粒度都在一个map中保存;在检索时,需要对起始和终止进行粒度处理,同时仅检索需要的粒度map即可。
class LogSystem {
public:
map<int,string> record[6];//一条记录保存六种粒度情况
string gra_index[6] = {"Year", "Month", "Day", "Hour", "Minute", "Second"};//方便给出一个粒度,找到对应的map
LogSystem() {
for(int i=0;i<6;++i)
record[i]=map<int,string>();
}
void put(int id, string timestamp) {
int t=timestamp.size()-1;
for(int i=5;i>=0;--i){//对记录进行粒度操作
record[i][id]=timestamp;//先保存记录到相应的粒度索引的map中
while(t>=0&×tamp[t]!=':')//然后对记录的粒度进行擦除,便于在下次循环进行保存
timestamp[t--]='x';
--t;
}
}
vector<int> retrieve(string s, string e, string gra) {
int j=0;
for(;j<6&&gra_index[j]!=gra;++j);//先找到需要的粒度对应的索引下标
for(int t=s.size()-1,cnt=5-j;t>=0&&cnt>0;--t){//对s和e的剩余部分粒度进行擦除,其中cnt为需要擦除的个数,遇到:则减1,当为0时代表已擦除
if(s[t]==':')
cnt--;
else
s[t]='x';
}
for(int t=e.size()-1,cnt=5-j;t>=0&&cnt>0;--t){
if(e[t]==':')
cnt--;
else
e[t]='x';
}
vector<int> res;
for(auto i:record[j]){//此时只需到要求粒度的map中进行检索即可,由于s和e都根据所需粒度统一了,所以记录之间可以比较大小来确定范围,保存id
if(i.second>=s&&i.second<=e)
res.push_back(i.first);
}
return res;
}
};
/**
* Your LogSystem object will be instantiated and called as such:
* LogSystem obj = new LogSystem();
* obj.put(id,timestamp);
* vector<int> param_2 = obj.retrieve(s,e,gra);
*/