【问题标题】:Trying to solve Top K Frequent Elements using a LinkedList尝试使用 LinkedList 解决 Top K 频繁元素
【发布时间】:2019-03-02 21:10:12
【问题描述】:

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

1) 取输入数组,例如:[1,1,1,2,2,3]

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

3) 使用包含整数->频率对的节点创建一个 LinkedList,并按频率升序将元素插入到此 LinkedList 中,即。 head->[1,3]->[2,2]->[3,1]->null

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 而不是正确的排序方式。我已经尝试调试它,但无法弄清楚我搞砸了哪一部分。我还把它写在纸上,它似乎可以工作,所以我确定我的代码搞砸了。

我在这里做错了什么?

【问题讨论】:

  • 使用最大堆代替链表,性能更好
  • 您的排序算法有缺陷。假设您插入一个频率为 2 的项目,然后插入一个频率为 3 的项目。频率 3 的项目现在应该位于列表的开头(即,sortedList 现在应该指向频率为 3 的项目)。但是,一旦第一个项目被输入到列表中,就再也不会改变sortedList
  • @KevinAnderson 我的 while 循环会以频率 3 将该项目传播到头部。
  • @FlameDra 只有两个选项:1) sortedList = newNodesortedList 为空时,或 2) current.next = newNodesortedList 不为空时。当sortedList 不为空时,您的代码中的任何内容都不会设置sortedList = newNode。换句话说,凯文是对的。

标签: java algorithm linked-list


【解决方案1】:

问题在于您尝试将链表插入到排序顺序的代码中。首先是您从current.next.data 开始比较,您应该从第一个节点开始比较。其次,您没有处理必须在最后一个节点和第一个节点插入元素的情况。并且您有条件&lt;,这意味着它将按降序插入。

在地图迭代代码中替换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 意味着数据必须插入到最后一个节点和那个时候最后一个节点将被prev引用所以prev.next=newNode;将分配newNode 到最后。 如果current==sortedList 表示必须在第一个节点插入数据。否则需要在中间插入数据。

【讨论】:

    猜你喜欢
    • 2022-11-28
    • 2023-02-07
    • 2021-05-16
    • 1970-01-01
    • 2020-11-15
    • 2019-09-20
    • 2021-07-08
    • 2019-10-09
    • 1970-01-01
    相关资源
    最近更新 更多