LeetCode82 删除排序链表中的重复元素

Question

给定一个已排序的链表的头 head , 删除原始链表中所有重复数字的节点,只留下不同的数字 。返回 已排序的链表 。
LeetCode82 删除排序链表中的重复元素_第1张图片

方法一 当然是递归大法

  • 当head后面有值并且和head的值相等,则一直找到与head不相等为止,然后对后面一个结点去递归,这样就删除了前面重复的结点
  • 当head后面有值且与head的值不相等时,那么就递归后面一个结点,跟在head后面
  • 最后返回head

思路还是很简单的,代码如下:

/**
 * 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 head;
        }
        if (head->next && head->val == head->next->val){//如果有下一个结点且下一个结点相同
            while (head->next && head->val == head->next->val){//如果一直相同就一直循环
                head = head->next;
            }
            return deleteDuplicates(head->next);//好了,遇到不同的了,返回进去(因为是删除所有相同的数,所以是从head->next开始)
        }else {//当不同时,赋值从下一个结点开始递归
            head->next = deleteDuplicates(head->next);//只要不同就接在后面
        }
        return head;
    }
};

方法二 学习了别人的做法

  • 定义一个dummy头结点,链接上原链表,cur指向原链表头部
  • ①当前结点value != 当前结点的下一结点value。那么让pre指针来到当前结点,这样就链接了前一结点和当前结点。然后当前结点移至下一结点
  • ②当前结点value == 当前结点的下一结点value。那么就让cur一直往下走直到当前结点value != 当前结点的下一结点value,然后此时是不能动pre指针的,要避免后面还有重复的,所以让pre->next = cur->next。然后当前结点移至下一结点。
  • 循环结束的条件结合子例即可。
/**
 * 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;//如果头结点为空或者没有下一个值了
        }

        ListNode* dummy = new ListNode(-1);
        dummy->next = head;//定义了一个头结点dummy

        //两个指针都从头开始
        ListNode* pre = dummy;
        ListNode* cur = head;
        while (cur && cur->next) {//cur一直往下走
            if (cur->val == cur->next->val) {//如果cur遇到的当前结点等于下一结点
                while(cur->next && cur->val == cur->next->val) {
                    cur = cur->next;//遍历所有这些相同的结点直到不相等
                }
                pre->next = cur->next;//将下一结点的值赋给pre当前结点的下一个值
                cur = cur->next;//当前结点移至下一结点
            }else{//如果cur遇到的当前结点不等于下一结点,直接让pre来到当前结点,当前结点移至下一结点
                pre = cur;
                cur = cur->next;
            }
        }
        return dummy->next;
    }
};

大概流程图
LeetCode82 删除排序链表中的重复元素_第2张图片
总结:相当于一开始cur就是要遍历所有结点的,最后通过返回dummy来确定答案,那么方法二的关键也就是pre的位置,cur每找到一个与下一个结点相同的结点先不能将pre调过去,避免后面还有重复的,当cur找到一个与下下一个结点不相同的结点(或下一结点为NULL)时,再把pre调过去,这样就可以直接跳过所有相同的值了!

你可能感兴趣的:(LeetCodeLife,c++,算法,数据结构)