在 O(1) 时间内删除链表节点
题目描述
给定单向链表的头指针和一个结点指针,定义一个函数在O(1)时间内删除该节点。
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
解题思路
① 如果该节点不是尾节点,那么可以直接将下一个节点的值赋给该节点,然后令该节点指向下下个节点,再删除下一个节点,时间复杂度为 O(1)。
② 否则,就需要先遍历链表,找到节点的前一个节点,然后让前一个节点指向 null,时间复杂度为 O(N)。
综上,如果进行 N 次操作,那么大约需要操作节点的次数为 N-1+N=2N-1,其中 N-1 表示 N-1 个不是尾节点的每个节点以 O(1) 的时间复杂度操作节点的总次数,N 表示 1 个尾节点以 O(N) 的时间复杂度操作节点的总次数。(2N-1)/N ~ 2,因此该算法的平均时间复杂度为 O(1)。
注意:假设要删除的节点在链表中。
ListNode* deleteNode(ListNode* head, ListNode* tobeDelete) {
if(!head || !tobeDelete) return nullptr;
if(tobeDelete->next) {
ListNode *next = tobeDelete->next;
tobeDelete->val = next->val;
tobeDelete->next = next->next;
delete next;
} else {
if(head->next) {
ListNode *cur = head;
while(cur->next != tobeDelete) cur = cur->next;
ListNode *next = cur->next;
cur->next = nullptr;
delete next;
} else head = nullptr;
}
return head;
}
删除链表中重复的结点
NowCoder LeetCode
题目描述
在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->2->3->3->4处理后为 1->4。
解题思路
前中后三指针把控
class Solution {
public:
ListNode* deleteDuplication(ListNode* pHead) {
if(!pHead) return pHead;
ListNode *pre = nullptr, *cur = pHead, *nex = nullptr;
while(cur) {
if(cur->next && (cur->next->val == cur->val)) {
nex = cur->next;
while (nex->next && (nex->next->val == nex->val)) nex = nex->next;
if(cur == pHead) pHead = nex->next;
else pre->next = nex->next;
cur = nex->next;
} else {
pre = cur;
cur = cur->next;
}
}
return pHead;
}
};
新建头结点
class Solution {
public:
ListNode* deleteDuplication(ListNode* pHead) {
if(!pHead) return nullptr;
ListNode* first = new ListNode(-1);//设置一个trick
first->next = pHead;
ListNode* p = pHead, *last = first;
while(p->next) {
if(p->next->val == p->val) {
while (p->next && p->next->val == p->val) p = p->next;
last->next = p->next;
if(p->next) p = p->next;
} else {
last = p;
p = p->next;
}
}
return first->next;
}
};
递归
class Solution {
public:
ListNode* deleteDuplication(ListNode* pHead) {
if (!pHead || !pHead->next) return pHead; // 只有0个或1个结点,则返回
if (pHead->val == pHead->next->val) { // 当前结点是重复结点
ListNode* pNode = pHead->next;
// 跳过值与当前结点相同的全部结点,找到第一个与当前结点不同的结点
while (pNode && pNode->val == pHead->val) pNode = pNode->next;
// 从第一个与当前结点不同的结点开始递归
return deleteDuplication(pNode);
} else { // 当前结点不是重复结点
// 保留当前结点,从下一个结点开始递归
pHead->next = deleteDuplication(pHead->next);
return pHead;
}
}
};
Leetcode 83 答案
class Solution {
public:
ListNode* deleteDuplicates(ListNode* head) {
if(head == NULL || head->next == NULL) return head;
head->next = deleteDuplicates(head->next);
return head->val == head->next->val ? head->next : head;
}
};