题目描述
在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表 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. 保留一个重复的结点
参考文献:
【1】Kotlin中 ?、!!、?:、:: 、->符号的简单说明
【2】使用 Option 类型来处理缺失 - Learn | Microsoft Docs