繁体   English   中英

是什么可以使该代码更高效(针对Hackerrank问题)?

[英]What could make this code more efficient (for Hackerrank problem)?

请参阅我编写的解决此hackerrank挑战的代码。

https://www.hackerrank.com/challenges/frequency-queries/problem?h_l=interview&playlist_slugs%5B%5D=interview-preparation-kit&playlist_slugs%5B%5D=dictionaries-hashmaps

从本质上讲,在这一点上,我知道我的代码在算法上足够快,可以接受此挑战,因为我所做的完全是编辑部分中讨论的内容。 但是,代码由于超时而终止。 因此,我想知道我使用的数据结构是否存在明显的低效率,或者是否可能是内存问题或其他问题。 另外,值得注意的是,社论是用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中。 否则,我将0添加到结果ArrayList中。

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的长度。

愚蠢的我没有检查讨论部分,显然在查询中读取的样板代码太慢了,这主要是由于已经讨论过使用List中的get()显然是O(n)的复杂性。 最重要的是,对于add()的结果,应该使用LinkedList而不是用于O(1)复杂度的ArrayList。

我所做的更改实际上是从List<List<Integer>>更改为List<int[]> ,从而在恒定时间内访问查询和值。 如果输入长度已知,我也可以通过简单地使用二维数组来更快。

另外,在读取输入时,我会统计有多少查询需要我向结果列表中实际添加一个值,例如n,并将其传递给我的方法。 有了这些知识,我就可以实例化一个数组int [n],然后也可以在恒定时间内将其添加到结果数组中。 快多了

更加整洁,更接近您的工作:

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;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM