给定一个排序链表,删除所有含有重复数字的节点,只保留原始链表中 没有重复出现 的数字。

版权声明: https://blog.csdn.net/if_i_were_a/article/details/89093043

与这个题相似的有一道题,保留原始链表中重复数字出现一次

博客地址:https://blog.csdn.net/if_i_were_a/article/details/89092123

本题的题目描述:(本题是LeetCode第82题)

给定一个排序链表,删除所有含有重复数字的节点,只保留原始链表中 没有重复出现 的数字。

示例 1:

输入: 1->2->3->3->4->4->5
输出: 1->2->5

示例 2:

输入: 1->1->1->2->3
输出: 2->3

思路:与上一道题相比,这道题不同之处在于他要把所有的重复值节点都删完,前一道题的思路在于当前的值跟下一个值比较,如果重复,删除下一个,如果不重复,就继续遍历下一个元素。但是相对于这道题,当前的值即使跟下一个不相等,也有可能与之前重复过的相等。那么如何保证在这种情况下的时间复杂度为0(1)呢,可以使用一个计数器,如果有与当前节点重复的节点,删除掉重复节点之后(因为该链表是有序的,所以重复的就是当前节点的下一个),计数器的值加一。当前节点重复值删除完之后,判断当前节点是否需要删除就是判断计数器的值是否为0,如果不是0则删除该节点。然后继续遍历

有两种特殊情况,当前节点有重复在链表的头和链表的尾。当为头的时候,因为该链表是不带表头的节点,所以有两种解法,加虚拟表头结点或者分为判断是否为为表头结点,是和不是分为两种情况。对于尾节点来说,因为出循环之后还要判断尾节点是否重复过,如果重复过,删除尾节点。代码如下:
 

public static ListNode deleteDuplicates1(ListNode head) {
        //添加一个虚拟的表头结点
        ListNode tempHead = new ListNode(0);
        tempHead.next = head;
        //pre之前虚拟头结点,记录元素的前一个位置,如果要删除当前元素,需要前一个位置的指针
        ListNode cur = head, pre = tempHead;
        //计数器的初始值置为0
        int count = 0;
        //当前链表为空或者遍历到链表的最后一个元素时
        while (cur != null && cur.next != null) {
            //如果当前节点和下一个结点相等,删除下一个结点,计数值加1
            if (cur.val == cur.next.val) {
                cur.next = cur.next.next;
                count++;
            } else {
                //不相等的情况下需要判断计数值是否为0来确定是否需要删除当前节点
                if (count > 0) {
                    pre.next = cur.next;
                    count = 0;
                } else {
                    pre = cur;
                }
                cur = cur.next;
            }
        }
        //判断尾节点是否需要删除
        if (count > 0) {
            pre.next = cur.next;
        }
        //返回去除虚拟头结点的链表
        return tempHead.next;
    }

贴一个总体的代码,方便给需要的人

public class Num83 {
    public static void main(String[] args) {
        int[] arr = new int[]{1, 1, 1, 2, 3};
        //删除链表中的重复元素,保留一个
        ListNode head = new ListNode(arr);
        head = deleteDuplicates1(head);
        System.out.println(head.toString());
    }

    public ListNode deleteDuplicates(ListNode head) {
        //设置一个指向当前元素的指针
        ListNode current = head;
        //当链表为空或者链表中遍历到最后一个元素时,出循环
        while (current != null && current.next != null) {
            //如果找到当前节点和它的下一个结点的值相同,删除掉下一个结点
            if (current.next.val == current.val) {
                current.next = current.next.next;
            } else {
                //如果没有找到,当前节点后移
                current = current.next;
            }
        }
        return head;
    }


    public static ListNode deleteDuplicates1(ListNode head) {
        //添加一个虚拟的表头结点
        ListNode tempHead = new ListNode(0);
        tempHead.next = head;
        //pre之前虚拟头结点,记录元素的前一个位置,如果要删除当前元素,需要前一个位置的指针
        ListNode cur = head, pre = tempHead;
        //计数器的初始值置为0
        int count = 0;
        //当前链表为空或者遍历到链表的最后一个元素时
        while (cur != null && cur.next != null) {
            //如果当前节点和下一个结点相等,删除下一个结点,计数值加1
            if (cur.val == cur.next.val) {
                cur.next = cur.next.next;
                count++;
            } else {
                //不相等的情况下需要判断计数值是否为0来确定是否需要删除当前节点
                if (count > 0) {
                    pre.next = cur.next;
                    count = 0;
                } else {
                    pre = cur;
                }
                cur = cur.next;
            }
        }
        //判断尾节点是否需要删除
        if (count > 0) {
            pre.next = cur.next;
        }
        //返回去除虚拟头结点的链表
        return tempHead.next;
    }


    static class ListNode {
        int val;
        ListNode next;

        ListNode(int x) {
            val = x;
        }

        public ListNode(int[] arr) {
            if (arr == null || arr.length == 0)
                throw new IllegalArgumentException("arr can to be empty");
            this.val = arr[0];
            ListNode cur = this;
            for (int i = 1; i < arr.length; i++) {
                cur.next = new ListNode(arr[i]);
                cur = cur.next;
            }
        }

        @Override
        public String toString() {
            StringBuilder res = new StringBuilder();
            ListNode cur = this;
            while (cur != null) {
                res.append(cur.val + "->");
                cur = cur.next;
            }
            res.append("NULL");
            return res.toString();
        }
    }
}

本函数在LeetCode上运行成功,无毒无害,可以使用哦

猜你喜欢

转载自blog.csdn.net/if_i_were_a/article/details/89093043