《剑指offer》76--删除链表中重复的结点[C++][C][Java][Kotlin][Rust]

删除链表中重复的结点_牛客题霸_牛客网【牛客题霸】收集各企业高频校招笔面试题目,配有官方题解,在线进行百度阿里腾讯网易等互联网名企笔试面试模拟考试练习,和牛人一起讨论经典试题,全面提升你的技术能力https://www.nowcoder.com/practice/fc533c45b73a41b0b44ccba763f866ef?tpId=13&tqId=23450&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking

题目描述

在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表 1->2->3->3->4->4->5  处理后为 1->2->5

解题思路

【C++解法】

1、使用set,暴力解法

时间复杂度:O(2n),遍历了2次单链表
空间复杂度:最坏O(n), 最好O(1)

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
        val(x), next(NULL) {
    }
};
*/
class Solution {
public:
    ListNode* deleteDuplication(ListNode* pHead) {
        if (!pHead) {return pHead;}
        set<int> st;
        ListNode *pre = pHead;
        ListNode *cur = pHead->next;
        while (cur) {
            if (pre->val == cur->val) {
                st.insert(pre->val);
            }
            pre = pre->next;
            cur = cur->next;
        }
        ListNode *vHead = new ListNode(-1);
        pre = vHead;
        cur = pHead;
        while (cur) {
            if (st.count(cur->val)) {
                cur = cur->next;
            } else {
                pre->next = cur;
                pre = pre->next;
                cur = cur->next;
            }
        }
        pre->next = nullptr;
        return vHead->next;
    }
};

2、遍历直接删除

时间复杂度:O(n)
空间复杂度:O(1)

双指针迭代

class Solution {
public:
    ListNode* deleteDuplication(ListNode* pHead) {
        ListNode *vHead = new ListNode(-1);
        vHead->next = pHead;
        ListNode *pre = vHead, *cur = pHead;
        while (cur) {
            if (cur->next && cur->val == cur->next->val) {
                cur = cur->next;
                while (cur->next && cur->val == cur->next->val) {
                    cur = cur->next;
                }
                cur = cur->next;
                pre->next = cur;
            } else {
                pre = cur;
                cur = cur->next;
            }
        }
        pre->next = nullptr;
        return vHead->next;
    }
};

换一种思路:

class Solution {
public:
    ListNode* deleteDuplication(ListNode* pHead) {
        ListNode *vHead = new ListNode(-1);
        ListNode *tail = vHead, *cur = pHead;
        while (cur) {
            if (!cur->next || cur->val != cur->next->val) {
                tail->next = cur;
                tail = cur;
            }
            while (cur->next && cur->val == cur->next->val) {cur = cur->next;}
            cur = cur->next;
        }
        tail->next = nullptr;
        return vHead->next;
    }
};

 变量更少一些:

// 一次遍历,更少变量
class Solution {
public:
    ListNode* deleteDuplication(ListNode* pHead) {
        ListNode *vHead = new ListNode(-1);
        vHead->next = pHead;
        ListNode *cur = vHead;
        while (cur->next && cur->next->next) {
            if (cur->next->val == cur->next->next->val) {
                int x = cur->next->val;
                while (cur->next && cur->next->val == x) {
                    cur->next = cur->next->next;
                }
            } else {
                cur = cur->next;
            }
            
        }
        return vHead->next;
    }
};

3、递归

时间复杂度:O(n)
空间复杂度:忽略递归带来的额外空间开销,O(1)

class Solution {
public:
    ListNode* deleteDuplication(ListNode* pHead) {
        if (pHead == nullptr || pHead->next == nullptr) {return pHead;}
        if (pHead->val != pHead->next->val) {
            pHead->next = deleteDuplication(pHead->next);
            return pHead;
        } else {
            ListNode* tmp = pHead->next;
            while (tmp != nullptr && tmp->val == pHead->val) {tmp = tmp->next;}
            return deleteDuplication(tmp);
        }
    }
};

【Java解法】

1、Set暴力解法

import java.util.HashSet;
public class Solution {
    public ListNode deleteDuplication(ListNode pHead) {
        if (pHead == null) {return pHead;}
        HashSet<Integer> st = new HashSet<>();
        ListNode pre = pHead;
        ListNode cur = pHead.next;
        while (cur != null) {
            if (pre.val == cur.val) {
                st.add(pre.val);
            }
            pre = pre.next;
            cur = cur.next;
        }
        ListNode vHead = new ListNode(-1);
        pre = vHead;
        cur = pHead;
        while (cur != null) {
            if (st.contains(cur.val)) {
                cur = cur.next;
            } else {
                pre.next = cur;
                pre = pre.next;
                cur = cur.next;
            }
        }
        pre.next = null;
        return vHead.next;
    }
}

2、遍历删除

public class Solution {
    public ListNode deleteDuplication(ListNode pHead) {
        ListNode vHead = new ListNode(-1);
        vHead.next = pHead;
        ListNode cur = vHead;
        while (cur.next != null && cur.next.next != null) {
            if (cur.next.val == cur.next.next.val) {
                int x = cur.next.val;
                while (cur.next != null && cur.next.val == x) {
                    cur.next = cur.next.next;
                }
            } else {
                cur = cur.next;
            }
        }
        return vHead.next;
    }
}

3、递归

public class Solution {
    public ListNode deleteDuplication(ListNode pHead) {
        if (pHead == null || pHead.next == null) {return pHead;}
        if (pHead.val != pHead.next.val) {
            pHead.next = deleteDuplication(pHead.next);
            return pHead;
        }
        ListNode tmp = pHead.next;
        while (tmp != null && tmp.val == pHead.val) {tmp = tmp.next;}
        return deleteDuplication(tmp);
    }
}

【C解法】

递归

struct ListNode* deleteDuplication(struct ListNode* pHead ) {
    if (pHead == NULL || pHead->next == NULL) {return pHead;}
    if (pHead->val != pHead->next->val) {
        pHead->next = deleteDuplication(pHead->next);
        return pHead;
    }
    struct ListNode* tmp = pHead->next;
    while (tmp != NULL && tmp->val == pHead->val) {tmp = tmp->next;}
    return deleteDuplication(tmp);
}

【Kotlin解法】

/**
 * class ListNode(var `val`: Int) {
 *     var next: ListNode? = null
 * }
 */


object Solution {
    /**
    * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
    * 
        * @param pHead ListNode类 
        * @return ListNode类
    */
    fun deleteDuplication(pHead: ListNode?): ListNode?  {
        if (pHead == null || pHead.next == null) {return pHead}
        if (pHead.`val` != pHead!!.next!!.`val`) {
            pHead.next = deleteDuplication(pHead.next)
            return pHead
        }
        var tmp : ListNode? = pHead.next
        while (tmp != null && tmp!!.`val` == pHead!!.`val`) {tmp = tmp!!.next}
        return deleteDuplication(tmp)
    }
}

【Rust解法】

/**
 *  #[derive(PartialEq, Eq, Debug, Clone)]
 *  pub struct ListNode {
 *      pub val: i32,
 *      pub next: Option<Box<ListNode>>
 *  }
 * 
 *  impl ListNode {
 *      #[inline]
 *      fn new(val: i32) -> Self {
 *          ListNode {
 *              val: val,
 *              next: None,
 *          }
 *      }
 *  }
 */

struct Solution{

}

impl Solution {
    fn new() -> Self {
        Solution{}
    }

    /**
    * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
    * 
        * @param pHead ListNode类 
        * @return ListNode类
    */
    pub fn deleteDuplication(&self, pHead: Option<Box<ListNode>>) -> Option<Box<ListNode>> {
        let mut head = pHead;
        let mut cur = head.as_mut();

        if cur.is_none() || cur.as_ref().unwrap().next.is_none() {
            return head
        }

        if cur.as_ref().unwrap().val != cur.as_ref().unwrap().next.as_ref().unwrap().val {
            let next = self.deleteDuplication(cur.as_ref().unwrap().next.clone());
            cur.as_mut().unwrap().next = next;
            return head
        }

        let mut tmp = cur.as_ref().unwrap().next.clone();
        while tmp.is_some() && tmp.as_ref().unwrap().val == cur.as_ref().unwrap().val {
            tmp = tmp.as_ref().unwrap().next.clone();
        }
        self.deleteDuplication(tmp)
    }
}

类似题目

1. 不保留重复节点

LeetCode-82. Remove Duplicates from Sorted List II [C++][Java]_贫道绝缘子的博客-CSDN博客Given theheadof a sorted linked list,delete all nodes that have duplicate numbers, leaving only distinct numbers from the original list. Returnthe linked listsortedas well.https://blog.csdn.net/qq_15711195/article/details/126191494?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22126191494%22%2C%22source%22%3A%22qq_15711195%22%7D&ctrtid=l6vHa

2. 保留一个重复的结点

LeetCode-83. Remove Duplicates from Sorted List [C++][Java]_贫道绝缘子的博客-CSDN博客Given theheadof a sorted linked list,delete all duplicates such that each element appears only once. Returnthe linked listsortedas well.https://blog.csdn.net/qq_15711195/article/details/122394297

参考文献:

【1】Kotlin中 ?、!!、?:、:: 、->符号的简单说明

【2】使用 Option 类型来处理缺失 - Learn | Microsoft Docs

【3】Rust填坑笔记--写一个简单的递归 - 知乎

【4】LeetCode笔记 83. 删除排序链表中的重复元素-C++与Rust实现

【5】Rust中,Some是什么类型? - 知乎

【6】Rust 链表! - 知乎

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

贫道绝缘子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值