如何从无序链表中移除重复项--Java版

本文介绍了两种方法去除无序链表中的重复项,保持原顺序。方法一是顺序删除,通过双重循环在链表上执行删除操作,时间复杂度为O(N^2),空间复杂度为O(1)。方法二是递归法,递归地处理子链表并删除重复节点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述:
给定一个没有排序的链表,去掉其重复项,并保留原顺序,如链表1->3->1->5->5->7,去掉重复项变为1->3->5->7

方法一:顺序删除

思路: 通过双重循环直接在链表上执行删除操作。外层循环用一个指针从第一个节点开始遍历整个链表,然后内层循环用另一个指针遍历其余节点,将与外层循环遍历到的指针所指节点的数据域相同的节点删除(删除的是内层循环的节点)。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode deleteDuplicates(ListNode head) {
    	//排除空表和单节点情况
        if (head == null || head.next == null) {
            return head;
        }
        ListNode outerCur = head;//用于外层循环,指向链表第一个节点
        ListNode innerCur = null;//内层循环用来遍历outerCur后面的节点
        //一旦涉及节点删除,那么就要找到该节点的前驱节点
        ListNode innerPre = null;//innerCur的前驱节点
        for (; outerCur != null; outerCur = outerCur.next) {
            for (innerCur = outerCur.next, innerPre = outerCur; innerCur != null; ) {
                //找到重复的节点并删除
                if (outerCur.val == innerCur.val) {
                    innerPre.next = innerCur.next;
                    innerCur = innerCur.next;
                } else {
                    innerPre = innerCur;
                    innerCur = innerCur.next;
                }
            }
        }
        return head;
    }
}

算法性能分析: 由于这种方法采用双重循环对链表进行遍历,因此,时间复杂度为O(N^2)。其中,N为链表的长度。在遍历链表的过程中,使用了常量个额外的指针变量来保存当前遍历的节点、前驱节点和被删除的节点,因此,空间复杂度为O(1)

方法二:递归法

思路: 对于节点cur,首先递归的删除以cur.next为首的子链表中重复的节点,接着从以cur.next为首的子链表中找出与cur有着相同的数据域的节点并删除。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode deleteDuplicates(ListNode head) {
        if(head == null || head.next == null){
            return head;
        }
        //对以head.next为首的子链表删除重复的节点
        head.next = deleteDuplicates(head.next);
        //找出以head.next为首的子链表中与head节点相同的节点并删除
        if(head.val == head.next.val){
            head = head.next;//此处直接切换头节点是最好的选择
        }   
        return head;
    }
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值