1、题目描述
2、解题思路
重新理解一下题意:
题目给 Put 输入为一个键值对,key 为 id,value 为一个字符串,表示时间戳;
题目从 Retrieve 获取一个 id,参数 granularity 表示起点从该级往下视为 0,终点从该级往下视为“满”,例如:“2016:01:01:01:01:01” 和 “2017:01:01:23:00:00”,如果 granularity 为 “YEAR” ,则把这两个字符串看成 “2016:00:00:00:00:00” 和 “2017:12:31:23:59:59”。
题目的难点在于如何根据给定的起点、终点和 granularity 获取 id。
考虑到字符串比较大小不方便,把时间戳转成一个数字,题目注释说给定的年份是 2000 年到 2017 年,我们可以把时间戳改成从 1999 年开始的秒数。
例如时间戳为:“2016:01:01:00:00:00”,先转成 int 数组:st = [2016, 1, 1, 0, 0, 0],接着计算出它从 [1999,0,0,0,0,0] 开始的秒数,即:
(st[0] - 1999L) * (31 * 12) * 24 * 60 * 60 + // 年
st[1] * 31 * 24 * 60 * 60 + // 月
st[2] * 24 * 60 * 60 + // 日
st[3] * 60 * 60 + // 时
st[4] * 60 + // 分
st[5]; // 秒
把时间戳对应的秒数和 id 存储到一个 list 中。
使用 Retrieve 函数时,计算出 start 对应的秒数和 end+1 对应的秒数,然后从 list 中找到这两个秒数之间的时间戳的 id 即可。
3、解题代码
public class LogSystem {
// [0] 为时间戳,[1] 为 id
ArrayList<long[]> list;
public LogSystem() {
list = new ArrayList<long[]>();
}
/**
* "2016:01:01:00:00:00" 转为 [2016, 1, 1, 0, 0, 0],再转为秒数,存入 list
* @param id
* @param timestamp
*/
public void put(int id, String timestamp) {
String[] strs = timestamp.split(":");
int[] st = new int[strs.length];
for (int i = 0; i < strs.length; i++) {
st[i] = Integer.parseInt(strs[i]);
}
list.add(new long[]{convert(st), id});
}
/**
* 将时间戳转换为从 1999 年开始到该时间戳的秒数
*
* @param st
* @return
*/
public long convert(int[] st) {
st[1] = st[1] - (st[1] == 0 ? 0 : 1);
st[2] = st[2] - (st[2] == 0 ? 0 : 1);
return (st[0] - 1999L) * (31 * 12) * 24 * 60 * 60 + // 由于本题中年份的限制在 [2000, 2017] 之间,因此我们可以将时间戳转换为从 1999 年开始到该时间戳的秒数。
st[1] * 31 * 24 * 60 * 60 + // 将每个月都看成 31 天,这样偏序关系仍然能够保持,只是有些整数没有对应的时间戳而已
st[2] * 24 * 60 * 60 + // 日
st[3] * 60 * 60 + // 时
st[4] * 60 + // 分
st[5]; // 秒
}
/**
* 返回在给定时间区间内的所有日志的 id
*
* @param s start 、 end 和 timestamp 的格式相同
* @param e
* @param gra granularity 表示考虑的时间级
* @return
*/
public List<Integer> retrieve(String s, String e, String gra) {
List<Integer> ans = new ArrayList();
long start = granularity(s, gra, false);
long end = granularity(e, gra, true);
for (int i = 0; i < list.size(); i++) {
// 注意 end 没有等于
if (list.get(i)[0] >= start && list.get(i)[0] < end)
ans.add((int) list.get(i)[1]);
}
return ans;
}
public long granularity(String s, String gra, boolean end) {
HashMap<String, Integer> h = new HashMap<>();
h.put("Year", 0);
h.put("Month", 1);
h.put("Day", 2);
h.put("Hour", 3);
h.put("Minute", 4);
h.put("Second", 5);
String[] res = new String[]{"1999", "00", "00", "00", "00", "00"};
String[] st = s.split(":");
for (int i = 0; i <= h.get(gra); i++) {
res[i] = st[i];
}
int[] t = new int[res.length];
for (int i = 0; i < res.length; i++) {
t[i] = Integer.parseInt(res[i]);
}
if (end) {
t[h.get(gra)]++;
}
return convert(t);
}
}
/**
* Your LogSystem object will be instantiated and called as such:
* LogSystem obj = new LogSystem();
* obj.put(id,timestamp);
* List<Integer> param_2 = obj.retrieve(s,e,gra);
*/