82. Remove Duplicates from Sorted List II

题目:

Given the head of a sorted linked list, delete all nodes that have duplicate numbers, leaving only distinct numbers from the original list. Return the linked list sorted as well.

 

Example 1:

Input: head = [1,2,3,3,4,4,5]
Output: [1,2,5]

Example 2:

Input: head = [1,1,1,2,3]
Output: [2,3]

 

Constraints:

  • The number of nodes in the list is in the range [0, 300].
  • -100 <= Node.val <= 100
  • The list is guaranteed to be sorted in ascending order.

 

 

思路1:

一道比较老的题,先将loop的思路,首先确定肯定需要双指针进行,因为要和前面的值比较。同时因为头并不一定是给定的那个head,比如是[1,1,2, 3],因此先令ans为空,然后在循环的时候判断,如果为空就直接赋值给它,否则就赋值给它的next。中间循环判断我写的有一点点复杂,感觉上代码结构可以继续优化,分两种情况:当前和前一节点相同,则一直往下走,找出第一个不同的节点,进行迭代更新然后参与下一轮循环;如果是不同的话直接赋值即可。最后一个点需要进行额外判断,判断方法也很简单,如果迭代的第一个节点存在但是下一个不存在,比如[1, 1, 2, 3, 5],p节点是5,这时候q是NULL,我们从q是无法判断的,但是如果p的下一个是NULL,那么这个最后的节点就是独一无二的。如果我们只用q判断[1, 1, 2, 3, 5, 5],因为5有过循环,q这时候一定是NULL,因此我们通过p而不是通过q来判断最后一个节点。

 

 

代码1:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* deleteDuplicates(ListNode* head) {
        if (!head)
            return NULL;
        ListNode* p = head;
        ListNode* q = p->next;
        if(!q)
            return p;
        ListNode* ans = NULL;
        ListNode* temp = ans;
        while (q)
        {
            if (p->val != q->val)
            {
                if (!ans)
                {
                    ans = p;
                    temp = ans;
                    temp->next = NULL;
                }
                else
                {
                    temp->next = p;
                    temp = temp->next;
                    temp->next = NULL;
                }
            }
            else
            {
                while (q&&p->val == q->val)
                {
                    q = q->next;
                }
            }
            p = q;
            if (p&&p->next)
                q = q->next;
            else
                q = NULL;
        }
        if (temp)
        {
            if(p && !p->next)
                temp->next = p;
        }
        else
            ans=p;
        return ans;
    }
};

 

 

思路2:

递归是个更加常规的思路,因为base case很明显,首先如果当前或者下一个是空,则直接返回空;如果当前和下一个不同,直接返回当前(这里对于最后一个节点的判断就很方便了,不用像loop一样需要额外考虑);如果当前和下一个节点的值相同的话,那就一直往下走,找到不同的那个节点再次递归。时间复杂度相同,但是从代码结构显然递归更适合。

 

 

代码2:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */

class Solution {
public:
    ListNode* deleteDuplicates(ListNode* head) {
        if(!head || !head->next)
            return head;
        if(head->val == head->next->val){
            int val = head->val;
            while(head && head->val == val)
                head = head->next;
            return deleteDuplicates(head);
        }
        else{
            head->next = deleteDuplicates(head->next);
            return head;
        }
    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值