美文网首页
算法---删除排序链表中的重复元素 II

算法---删除排序链表中的重复元素 II

作者: 小跑001 | 来源:发表于2020-08-16 10:12 被阅读0次

1 题目

给定一个排序链表,删除所有含有重复数字的节点,只保留原始链表中 没有重复出现 的数字。

示例 1:
输入: 1->2->3->3->4->4->5
输出: 1->2->5
示例 2:
输入: 1->1->1->2->3
输出: 2->3

(注: 来自leetcode)

2 解法一

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

struct ListNode* deleteDuplicates(struct ListNode* head){
    struct ListNode* cur = head;
    struct ListNode* root = NULL; // root 表示要返回的元素指针, 赋值给第一个唯一元素, 可以通过NULL来做判断是否为第一次赋值
    struct ListNode* pre = NULL; // 上一个唯一元素, 当找到一个唯一元素, 需要与上一个唯一元素连接起来
    while(cur) {
        bool cur_delete_flag = false; // 表示当前该元素是否该删除
        while (cur && cur->next && cur->val == cur->next->val) { // 循环出所有相等的元素
            cur = cur->next;
            cur_delete_flag = true;
        }

        if (!cur_delete_flag) {
            if (root == NULL) { // 表示第一个唯一的元素
                root = cur;
            }
            if (pre) {
                pre->next = cur; // 与上一个唯一元素连接起来
            }
            pre = cur;
        } else {
            if (pre) {
                pre->next = cur->next; // 舍弃掉相同的元素
            }
        }
        cur = cur->next;
    }

    return root;
}

3 解法二

解法2加了一个头节点, 让行为相对统一

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

struct ListNode* deleteDuplicates(struct ListNode* head) {
    if (head == NULL || head->next == NULL) {  // 假如是空或者只有一个元素就不用比较了
        return head;
    }

    struct ListNode tmp; // 作为头节点来表示第一个唯一元素
    struct ListNode* pre = &tmp; // 表示上一个唯一元素
    pre->next = head;
    struct ListNode* iter = pre->next->next;
    bool mark = false;
    while(iter != NULL){
        if (pre && pre->next->val == iter->val) {// 比较的是上一个唯一的元素的后面元素是否相等
            pre->next->next = iter->next; // 如果相等删除当前元素, 但不能删除pre->next, 留作后面的比较
            mark = true;
        } else { // 如果不相等
            if (mark) { // 说明pre->next相同过, pre不能改变, 但是要删除pre->next
                pre->next = iter;
                mark = false;
            } else { // 说明pre->next是唯一的元素, 要更新pre以及
                pre = pre->next;
            }
        }
        iter = iter->next;
    }

    if (mark) {  // 表示上pre->next相同过, 需要删除
        pre->next = NULL;
    }

    return tmp.next;
}

解法3

解法3和解法2类似, 只是多加了一层循环来找出与当前元素值不同的元素, 简洁了很多.

struct ListNode* deleteDuplicates(struct ListNode* head){
     if (head == NULL || head->next == NULL) {
        return head;
    }

    struct ListNode tmp;
    struct ListNode* pre = &tmp;
    pre->next = head;
    struct ListNode* cur = pre->next;
    while(cur) {
        while(cur && cur->next && cur->val == cur->next->val){ // 移动cur一直到与cur->next值不同 
            cur = cur->next;
        }

        if (pre->next == cur) { // 表示cur没移动过, 也就是唯一的元素值
            pre = cur;
        } else {
            pre->next = cur->next;
        }

        cur = cur->next;
    }

    return tmp.next;
}

相关文章

网友评论

      本文标题:算法---删除排序链表中的重复元素 II

      本文链接:https://www.haomeiwen.com/subject/ptyadktx.html