请参阅我为解决hackerrank挑战而编写的这段代码。
基本上,到现在为止,我知道我的代码在算法上足够快,可以接受此挑战,因为我所做的完全是编辑部分中讨论的内容。但是,代码由于超时而终止。因此,我想知道我使用的数据结构是否存在明显的低效率,或者是否可能是内存问题或其他问题。另外,值得注意的是,社论是用C ++编写的,而我的代码是用Java编写的
我将描述发生的情况。查询是要执行的查询的列表。 countMap是一个HashMap,它将存储给定数字出现在数组中的次数。 freqMap是一个HashMap,用于存储数组中出现次数为x(键)次的数字实例数。因此,例如,如果将数字5加到数组中,则将1加到countMap中键5的值上。然后,如果countMap中键5的值现在为6,这意味着5在数组中出现6次,我将在freqMap中键6的值加1,因为数字在数组中出现6次。然后,如果查询碰巧检查数组中是否有确切数字出现过6次,则可以直接在freqMap中检查,如果键6上的值> 0,则将数字1添加到结果ArrayList中。否则,我在结果ArrayList中添加一个0。
static List<Integer> freqQuery(List<List<Integer>> queries) {
HashMap<Integer,Integer> countMap = new HashMap();
HashMap<Integer,Integer> freqMap = new HashMap();
List<Integer> res = new ArrayList();
for(int i = 0; i < queries.size(); i++){
List<Integer> query = queries.get(i);
Integer qType = query.get(0);
Integer qVal = query.get(1);
if(qType == 1){
Integer countVal = countMap.get(qVal);
if(countVal == null){
countVal = new Integer(0);
}
countVal += 1;
countMap.put(qVal,countVal);
Integer freqVal = freqMap.get(countVal);
if(freqVal == null){
freqVal = new Integer(0);
}
freqVal += 1;
freqMap.put(countVal,freqVal);
if ((countVal - 1) > 0) {
Integer prevFreqVal = freqMap.get(countVal - 1);
prevFreqVal -= 1;
freqMap.put((countVal -1),prevFreqVal);
}
}else if(qType == 2){
Integer countVal = countMap.get(qVal);
if(countVal != null && countVal != 0){
countVal -= 1;
countMap.put(qVal,countVal);
Integer freqVal = freqMap.get(countVal);
if(freqVal == null){
freqVal = new Integer(0);
}
freqVal += 1;
freqMap.put(countVal,freqVal);
Integer prevFreqVal = freqMap.get(countVal + 1);
prevFreqVal -= 1;
freqMap.put((countVal + 1),prevFreqVal);
}
}else if(qType == 3){
Integer freqVal = freqMap.get(qVal);
if(freqVal == null || freqVal < 1){
res.add(0);
}else{
res.add(1);
}
}
}
return res;
}
所有结果都是正确的,但是出现超时错误,表明我的代码不够快。我不知道为什么会这样。
HashMap的获取和放置操作为O(1),一次遍历查询显然是O(q)。加到arraylist的末尾似乎是O(n),其中n是arraylist的长度。
答案 0 :(得分:0)
愚蠢的我没有检查讨论部分,显然在查询中读取的样板代码太慢了,这主要是因为已经讨论过要使用List中的get()显然是O(n)复杂性。最重要的是,对于add()的结果,应该使用LinkedList而不是用于O(1)复杂度的ArrayList。
我所做的更改实际上是从List<List<Integer>>
更改为List<int[]>
,从而在恒定时间内访问查询和值。如果输入长度已知,我还可以通过简单地使用二维数组来获得更快的速度。
此外,在读取输入内容时,我会统计有多少查询需要我向结果列表中实际添加一个值,例如n,并将其传递给我的方法。有了这些知识,我就可以实例化一个数组int [n],然后也可以在恒定时间内将其添加到结果数组中。快得多
答案 1 :(得分:0)
更干净,更接近您的工作
static List<Integer> freqQuery(List<List<Integer>> queries) {
Map<Integer, Integer> countMap = new HashMap<>();
Map<Integer, Integer> freqMap = new HashMap<>();
List<Integer> res = new LinkedList<>();
for (List<Integer> query : queries) {
Integer qType = query.get(0);
Integer qVal = query.get(1);
switch (qType) {
case 1:
Integer countVal = countMap.merge(qVal, 1, Integer::sum);
freqMap.merge(countVal, 1, Integer::sum);
freqMap.computeIfPresent(countVal - 1, (key, value) -> value - 1);
case 2:
countMap.computeIfPresent(qVal, (key, value) -> {
freqMap.merge(value, -1, Integer::sum);
freqMap.merge(value - 1, 1, Integer::sum);
return value - 1;
});
case 3:
Integer freqVal = freqMap.get(qVal);
res.add(freqVal == null || freqVal < 1 ? 0 : 1);
}
}
return res;
}