繁体   English   中英

从链表中删除重复项

[英]Remove Duplicates from Linked List

所以我有一个链接列表,我试图从中删除重复项。

我想到的基本算法是几乎使用跑步者技术。 我保留两个指针来比较相邻元素。 如果它们相同,我将 p1 的指针更改为指向 p1.next.next,否则我继续遍历列表。 但是,我在输入的解决方案中不断收到空指针异常。

Node RemoveDuplicates(Node head) {
  // This is a "method-only" submission. 
  // You only need to complete this method. 
    if (head == null){
        return null;
    } 

        Node current = head;
    Node runner = head;



    while(current != null && runner != null && runner.next != null){
    runner = runner.next;
    if(runner.data == current.data){
        if(current.next != null){
                    current = current.next.next; 

        }
    }else{
        current = current.next;
    }
}



    return current;
}

在我退出时,while 循环电流为空。 我认为这是问题所在。 我将如何返回更改列表的头部。

好的,虽然您已经接受了答案,但这里有一些示例代码,使用递归根据您在评论中的请求从有序列表中删除重复项。 (如果您的列表未订购,请订购 :) )

public Node removeDups(Node root) {
    if (root.next == null)
        return root;
    root.next = removeDups(root.next);
    if (root.data == root.next.data)
        return root.next;
    return  root;
} // call as root = removeDups(root);

正如您所提到的,这里并不真正需要递归,但是您使用的是递归定义的基于节点的链表。 因此,当它有意义时,解决方案的优雅有其好处。

我喜欢它的是你没有做任何node.next.next或需要检查那个null情况。 一旦堆栈开始展开,您就已经可以开始检查重复项了。 那么这只是比较root.dataroot.next.data 您已经知道两者都存在。

您可以使用 2 个指针进行单次遍历来完成此操作。此代码也适用于单个 while 循环。

public Node deleteDuplicates(Node head) {
        Node current=head;
            if (head == null)
                return null;
            else
            {
             Node runner=head.next;
               while(head.next!=null && runner!=null)
                {
                    if(head.val == runner.val)
                       prev=runner.next;
                    else
                    {
                      head.next=runner;
                      head=head.next;
                      prev=runner.next;
                    }
                }
                head.next=runner;
            }
            return current; 
    }

首先,您需要在最后返回 head,以便您返回列表,而不仅仅是最后一个元素。 其次,在某些情况下,您需要修改 .next 引用而不是分配它们。

请注意,如果列表未排序,这将不起作用。

之前:1 1 3 3
之后:1 3

这段代码有效(我已经测试过了)

static Node RemoveDuplicates(Node head) {
    if (head == null) return null;

    Node current = head;
    Node runner = head;

    while (current != null && current.next != null) {
        runner = current.next;
        while (runner != null && runner.data == current.data) {
            current.next = runner.next; // skip the repeat
            runner = runner.next;
        }
        current = current.next;
    }
    return head;
}

您可以在一次遍历中完成此操作。 只需维护两个指针 temp 和 next_of_next。 对每个节点进行temp迭代,当temp和下一个节点的数据相等时,将next_of_next指向temp后的替代节点,删除temp后的节点。

Node removeDuplicates(Node head)
{
    Node temp = head;
    Node next_of_next;
    if (head == null)    
        return;
    while (temp.next != null) 
    {
        if (temp.data == temp.next.data) 
        {
            next_of_next = temp.next.next;
            temp.next = null;
            temp.next = next_of_next;
        }
        else 
           temp = temp.next;
    }
return head ;
}

这是使用HashSet没有递归的解决方案:

public void RemoveDuplicates()
{
    if (head != null)
    {
        var hm = new HashSet<T>();
        Node current = head;
        Node prev = null;

        while (current != null)
        {
            if (!hm.Contains(current.Value))
            {
                hm.Add(current.Value);
                prev = current;
                current = current.Next;
            }
            else
            {
                prev.Next = current.Next;
                current = prev.Next;
            }
        }
    }
    return head;
}

暂无
暂无

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

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