题解 | #删除链表中重复的结点#

删除链表中重复的结点

http://www.nowcoder.com/practice/fc533c45b73a41b0b44ccba763f866ef

解法一:虚拟结点

此题要求删除「所有的」重复结点,而存在「原链表头结点出现重复」这种情况。因此,为了实现方便,定义虚拟结点dummy,其next指针指向原头结点。

思路如图所示。

图片说明
图片说明
图片说明

  1. 定义指针p,用以遍历链表;定义指针tail,用以指向当前「无重复链表」表尾;
  2. 每次p指针向前移动,并比较「当前位置取值」与「下一结点取值」是否相等:
    1. 若不相等,说明当前位置为非重复结点,更新tail指针;
    2. 否则,p指针不断向前移动直至「当前结点与下一结点取值不同为止」;
    3. 当p到达链表表尾而最外层while循环仍未结束,说明「链表表尾为非重复结点」,更新tail指针。

注意:在最外层while循环结束时,需要重置tail指针的next指针为空,否则无法完成「删除」这一操作。

代码实现:

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
        val(x), next(NULL) {
    }
};
*/
class Solution {
public:
    ListNode* deleteDuplication(ListNode* pHead) {
        if (!pHead) 
            return NULL;
        ListNode* dummy = new ListNode(-1); // 定义虚拟结点
        dummy->next = pHead; 
        ListNode* p = new ListNode(-1), *tail = new ListNode(-1); // p指针用来遍历链表,tail指针用来表示当前链表表尾
        p = pHead; 
        tail = dummy; 
        while (p) {
            if ((p->next && p->val != p->next->val) || !p->next) { // 如果无重复结点,或者达到了链表表尾
                // 更新tail指针
                tail->next = p; 
                tail = tail->next;
            }
            while (p->next && p->val == p->next->val) { // 有重复
                p = p->next; 
            }
            p = p->next; 
        }
        tail->next = NULL; // 重置tail指针next指针为空
        return dummy->next; 
    }
};

该方法需要遍历整个链表,时间复杂度为O(N);

该方法未使用额外空间(除部分指针外),空间复杂度为O(1)。

解法二:快慢指针

解法二的思路与解法一类似,思路如图所示:

图片说明

图片说明

图片说明

  1. 定义两个指针(slow、fast),以及虚拟结点dummy,初始化三者指针,slow和fast相邻;
  2. 当遇到重复时,「只有fast指针」向前移动,此时slow和fast不相邻;
  3. 若没有重复,则slow指针和fast指针都向前移动一步;

「因此,当出现重复时,slow指针和fast指针必不相邻,此时更新二者的位置可以实现删除的效果。」

据上述思路,实现的代码如下:

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
        val(x), next(NULL) {
    }
};
*/
class Solution {
public:
    ListNode* deleteDuplication(ListNode* pHead) {
        if (!pHead)
            return NULL;
        ListNode* slow = new ListNode(-1), *fast = new ListNode(-1), *dummy = new ListNode(-1); 
        dummy->next = pHead; 
        // 初始化两个指针
        slow = dummy; 
        fast = dummy->next; 
        while (fast) {
            // 遇到重复
            while (fast->next && fast->val == fast->next->val) {
                fast = fast->next; 
            }
            // 遇到重复
            if (slow->next != fast) {
                slow->next = fast->next; 
                fast = slow->next; 
            } else { // 没有重复
                fast = fast->next; 
                slow = slow->next; 
            }
        }
        return dummy->next;
    }
};

该方法需要遍历整个链表,时间复杂度为O(N);

该方法未使用额外空间(除部分指针外),空间复杂度为O(1)。

全部评论
ListNode* slow = new ListNode(-1); ... slow = dummy; 这样new的空间地址不是没保存了吗?就delete不掉了
点赞 回复 分享
发布于 2022-03-13 19:50

相关推荐

沉淀一会:**圣经 1.同学你面试评价不错,概率很大,请耐心等待;2.你的排名比较靠前,不要担心,耐心等待;3.问题不大,正在审批,不要着急签其他公司,等等我们!4.预计9月中下旬,安心过节;5.下周会有结果,请耐心等待下;6.可能国庆节前后,一有结果我马上通知你;7.预计10月中旬,再坚持一下;8.正在走流程,就这两天了;9.同学,结果我也不知道,你如果查到了也告诉我一声;10.同学你出线不明朗,建议签其他公司保底!11.同学你找了哪些公司,我也在找工作。
点赞 评论 收藏
分享
霁华Tel:秋招结束了,好累。我自编了一篇对话,语言别人看不懂,我觉得有某种力量在控制我的身体,我明明觉得有些东西就在眼前,但身边的人却说啥也没有,有神秘人通过电视,手机等在暗暗的给我发信号,我有时候会突然觉得身体的某一部分不属于我了。面对不同的人或场合,我表现出不一样的自己,以至于都不知道自己到底是什么样子的人。我觉得我已经做的很好,不需要其他人的建议和批评,我有些时候难以控制的兴奋,但是呼吸都让人开心。
点赞 评论 收藏
分享
1 2 评论
分享
牛客网
牛客企业服务