删除链表中重复的节点

《剑指offer》面试题18:题目二:删除链表中重复的节点。

题目:在一个排序的链表中,如何删除重复的节点?例如,链表{1,2,3,3,4,4,5},重复的节点删除后链表为{1,2,5}

思路:从头节点开始遍历链表,如果当前节点的值与下一个节点的值相同,那么它们就是重复的节点,都需要被删除。必须保证删除之后的链表仍然是相连的:要把当前节点的前一个节点与后面值比当前节点的值大的节点相连,中间重复的节点全部删除。如果从头节点开始就出现重复,则需要改变头节点的位置。

具体实现:定义三个节点变量:root,curNode,preNode分别代表链表的头节点,当前循环中遍历的节点,前一个节点。如果传入的头节点head为空,则直接返回头节点(即返回空);如果头节点不为空且头节点的下一个节点为空,即链表只有一个节点,返回头节点;如果头节点和头节点的下一个节点都不为空,则依次遍历链表中的节点,如果当前节点的值与下一个节点的值相同,则继续向后遍历直到当前节点的值与下一个节点next的值不同,然后判断当前节点是不是头节点,如果是头节点,则将root指向下一个节点next作为新的头节点。最后将preNode的指针域指向当前节点的下一个节点,然后curNode跳下一位。如果当前节点的值与下一个节点的值不同,则让preNode指向当前节点,当前节点跳下一位。最后函数返回链表的头节点root。

代码如下:

// 节点类
public class ListNode {
    int val;
    ListNode next;
    public ListNode(int val) {
        this.val = val;
    }
}

// 删除链表中重复节点的方法
public ListNode deleteDuplication(ListNode head) {
    if (head == null || head.next == null) {
        return head;
    }
    // 定义三个指针分别代表头指针,当前指针,当前指针的前一个指针
    ListNode root = head;
    ListNode preNode = head;
    ListNode curNode = head;
    // 循环遍历链表
    while (curNode != null && curNode.next != null) {
        // 当前节点的值等于下一个节点的值即为重复
        if (curNode.val == curNode.next.val) {
            // 向后查找所有重复的节点
            while (curNode.next != null && curNode.next.val == curNode.val) {
                curNode.next = curNode.next.next;
            }
            // 上面循环完成之后的当前节点curNode为重复的节点,需要删除。
            // 如果头指针等于当前节点,则将头指针指向当前节点的下一个节点(第一个不重复的数)
            if (root == curNode) {
                root = curNode.next;
            }
            // 让当前节点的前一个节点的next域指向当前节点的下一个节点
            preNode.next = curNode.next;
            // 当前指针跳下一位
            curNode = curNode.next;
        } else {
            // 当前节点和下一个节点不重复,则当前节点为下一次循环的前一个节点
            preNode = curNode;
            // 当前指针跳下一位
            curNode = curNode.next;
        }
    }
    // 返回链表头节点
    return root;
}

你可能感兴趣的:(删除链表中重复的节点)