【lettcode】删除有序链表中重复的元素


删除有序链表中重复的元素-I

在这里插入图片描述
这道题很简单,定义一个pre指针指向前,cur指向往后走,找到一个值不和pre相同的才停止,链接pre和cur,然后pre =cur,往后遍历即可。

/**
 * struct ListNode {
 *	int val;
 *	struct ListNode *next;
 * };
 */

class Solution {
    
    
public:
    /**
     * 
     * @param head ListNode类 
     * @return ListNode类
     */
    ListNode* deleteDuplicates(ListNode* head) {
    
    
        // write code here
        if(head == nullptr || head->next == nullptr)
            return head;
        ListNode* pre = head;
        ListNode* cur = pre;
        
        while(cur)
        {
    
    
            cur = cur->next;
            while(cur && cur->val == pre->val)
            {
    
    
                cur = cur->next;
            }
            pre->next = cur;
            pre = cur;         
        }
        
        return head;
    }
};

删除有序链表中重复的元素-II

删除有序链表中重复的元素-II
在这里插入图片描述

这道题的解题思路如下:首先从测试用例可以看出,重复的数字出现在链表头的时候我们是需要将链表头更改的,所以我们可以用一个哨兵位的头节点指向头。
其次难点在于:当出现下图的场景的时候,我们不能说next就一定是新的头部,我们这个时候应该要保持头head,然后下次cur指向next,next指向下一个位置,直到cur一开始就和next不相等(即类似cur为1,next为2的场景),才能说明cur是出现了一次,这个时候才能更新头部。
在这里插入图片描述
一个例子:
在这里插入图片描述

class Solution {
    
    
public:
	/**
	 *
	 * @param head ListNode类
	 * @return ListNode类
	 */
	ListNode* _deleteDuplicates(ListNode* head, ListNode* start)
	{
    
    
		if (head == nullptr || head->next == nullptr)
			return head;
		ListNode* cur = start;
		ListNode* next = cur->next;
		while (next && next->val == cur->val)
		{
    
    
			next = next->next;
		}
        //这里有特殊情况,若刚好cur为第一次出现并且next为空的情况,cur也是第一次出现。
		if (next == cur->next) {
    
    
			//这里说明cur一定是出现一次的,cur就是新的头,next就是下次cur遍历的位置
			head->next = cur;
			start = next;
		}
		else if (next == nullptr)
		{
    
    
			head->next = next;
			return head;
		}
		else {
    
    
			//这里表示头不变,并且下次cur需要从next位置出发,所以设置start
			cur = head;
			start = next;
		}
		return _deleteDuplicates(cur, start);
	}

	ListNode* deleteDuplicates(ListNode* head) {
    
    
		// write code here
		//会跟换头
		ListNode* dummy = new ListNode(-1);
		dummy->next = head;
		_deleteDuplicates(dummy, dummy->next);

		return dummy->next;
	}
};

鸠摩罗什的解法:更加优秀,空间复杂度为O(1)。
思想在于,在p->next的val与当前的val相同的情况下,通过改变p->next的指向,从而让第一个开始重复的从链表断开,此时p则一直指向头部,直到出现一开始就不相等的情况就更新p(头部)。

class Solution {
    
    
public:
    ListNode* deleteDuplicates(ListNode* head) {
    
    
        ListNode* dummp = new ListNode(-1);
        dummp->next = head;     //空节点插入链表头部
        ListNode* p = dummp;

        while(p->next && p->next->next){
    
          //每次都是2个节点判断
            if(p->next->val == p->next->next->val)
            {
    
          
                //存在重复节点
                int num_flag = p->next->val;          //记录第一个重复节点的值
                while(p->next && p->next->val == num_flag)    //循环遍历后续节点的值,并与记录的节点值比较,相同则逐个删除
                {
    
    
                    //即将p设置为第一个不为num_flag的节点
                    p->next = p->next->next;
                }
            }
            else 
            {
    
    
                //本轮不存在重复节点,值链表指针后移
                p = p->next;
            }
        }
        return dummp->next;    //返回结果
    }
};

猜你喜欢

转载自blog.csdn.net/weixin_52344401/article/details/124344135