尝试使用LinkedList解决前K个常见元素

时间:2018-09-27 02:58:22

标签: java algorithm linked-list

我正在尝试解决LeetCode #347. Top K Frequent Elements。我知道解决此问题的几种方法,但我正尝试通过以下方式进行。

1)以输入数组为例:[1,1,1,2,2,3]

2)创建一个整数出现频率的映射,即。 {[1,3],[2,2],[3,1]}

3)用包含整数->频率对的节点创建一个LinkedList,并以频率的升序将元素插入此LinkedList。头-> [1,3]-> [2,2]-> [3,1]->空

4)打印此LinkedList的前k个值元素,即[1,2]

理论上应该给我正确的答案。

我正在使用以下实现:

class Solution {
    public List<Integer> topKFrequent(int[] nums, int k) {
        /*  input: [1,1,1,2,2,3], 2
            result: [1,3]
            expected: [1,2]
        */

        //stores integer->frequency pairs
        Map<Integer, Integer> map = new HashMap<Integer, Integer>();

        Node sortedList = null; //head node of list

        List<Integer> res = new ArrayList<Integer>(); //result array

        //populate map with integer->frequency pairs
        for(int i : nums) {
            if(map.containsKey(i)) {
                map.put(i, map.get(i)+1);
            } else {
                map.put(i, 1);
            }
        }

        //System.out.println(map);

        //go through map
        for(Map.Entry<Integer, Integer> entry : map.entrySet()) {

            Integer key = entry.getKey();
            Integer value = entry.getValue();

            List<Integer> pair = new ArrayList<Integer>(); //make a pair
            pair.add(key);
            pair.add(value);

            //System.out.println(pair);

            Node newNode = new Node(pair);

            System.out.println(newNode.data);

            if(sortedList == null) {
                //System.out.println(newNode.data);
                newNode.next = sortedList;
                sortedList = newNode; //insert at head if linked list is empty
            } else {
                Node current = sortedList; //point current to head
                //move current pointer until we find a spot where current's frequency is less than newNode's frequency
                while(current.next != null && current.next.data.get(1) < newNode.data.get(1)) {
                    current = current.next;
                }
                    newNode.next = current.next;
                    current.next = newNode;
            }

        }

        int count = 0;

        //loop until k and return first k keys
        while(sortedList != null && count < k) {
            //System.out.println("key:"+sortedList.data.get(0) + " value:"+ sortedList.data.get(1));
            res.add(sortedList.data.get(0));
            sortedList = sortedList.next;
            count++;
        }


        return res;
    }

    class Node {     
        List<Integer> data = new ArrayList<Integer>();
        Node next;

        Node(List<Integer> pair) {
            data = pair;
        }
    }
}

但是,由于某种原因,我的LinkedList填充为head-> [1,3]-> [3,1]-> [2,2]-> null,而不是正确的排序方式。我已经尝试调试它,但无法弄清楚我搞砸了哪一部分。我也已经将其写在纸上,并且似乎可以正常工作,因此我确定自己的代码中有些混乱。

我在这里做什么错了?

1 个答案:

答案 0 :(得分:1)

问题在代码段中,您尝试在其中按排序顺序将其插入链表。第一件事是您从current.next.data开始比较,您应该从第一个节点开始比较。其次,当元素必须在最后一个节点以及第一个节点插入时,您没有处理这种情况。并且您有条件<,这意味着它将以降序插入。

在地图迭代代码替换 if else条件中添加以下代码。效果很好

 if(sortedList == null) {
                    //System.out.println(newNode.data);
                    newNode.next = sortedList;
                    sortedList = newNode; //insert at head if linked list is empty
                } else {
                    Node current = sortedList; //point current to head
                    Node prev=null;
                    //move current pointer until we find a spot where current's frequency is less than newNode's frequency
                    while(current != null && current.data.get(1) > newNode.data.get(1)) {
                        prev=current;
                        current = current.next;
                    }
                    if(current==null) {
                        prev.next=newNode;
                    }else if(current==sortedList) {
                        newNode.next=current;
                        sortedList=newNode;
                    }
                    else {
                        newNode.next = current.next;
                        current.next = newNode;
                    }


                }

如果current==null表示必须在最后一个节点和最后一个节点插入数据,并且此时上一个节点将被上一个引用,所以{{1 }}将newNode分配给last。 如果prev.next=newNode;表示必须在第一个节点上插入数据。否则需要在中间插入数据。