题目一:删除链表节点
给定单向链表的头指针和一个要删除的节点的值,定义一个函数删除该节点。
返回删除后的链表的头节点。
注意:此题对比原题有改动
示例 1:
输入: head = [4,5,1,9], val = 5
输出: [4,1,9]
解释: 给定你链表中值为 5 的第二个节点,那么在调用了你的函数之后,该链表应变为 4 -> 1 -> 9.
示例 2:
输入: head = [4,5,1,9], val = 1
输出: [4,5,9]
解释: 给定你链表中值为 1 的第三个节点,那么在调用了你的函数之后,该链表应变为 4 -> 5 -> 9.
解法一:单指针扫描法
思路:
- 遍历链表,开始在
p=head
处考虑。 - 当
p->val == val
时,删除p,返回p后面的链表头节点。 - 当
p->next->val != val
时,向后遍历,直到p->next->val == val
时止。删除p->next
即可。
代码实现:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* deleteNode(ListNode* head, int val) {
if(head == nullptr) return nullptr;
ListNode * cur = head;
if(cur->val == val){
head = head->next;
return head;
}
while(cur->next && cur->next->val != val){
cur = cur->next;
}
if(cur->next && cur->next->val == val) {
cur->next = cur->next->next;
}
return head;
}
};
解法二:递归法
思路:
- 遍历链表,在节点head处考虑。
- 当head.val == val时,要删除head节点,那么,返回节点后面的链表头head->next。
- 当head.val != val时,要在head节点之后的部分继续删除。递归执行删除算法。
注意删除后,剩余的链表要再次拼接到head的后面。
代码实现:
class Solution {
public:
ListNode* deleteNode(ListNode* head, int val) {
if(head == nullptr) return nullptr;
if(head->val == val) return head->next;
head->next = deleteNode(head->next, val);
return head;
}
};
剑指Offer源代码
struct ListNode{
int m_value;
ListNode* m_pnext;
};
// 基于一个假设:要删除的节点在链表中
void DeleteNode(ListNode ** pListHead, ListNode * pToBeDeleted){
if(!pListHead || !pToBeDeleted) return;
// 要删除的节点不是尾节点
if(pToBeDeleted->m_pnext != nullptr){
ListNode * pNext = pToBeDeleted->m_pnext;
pToBeDeleted->m_value = pNext->m_value;
pToBeDeleted->m_pnext = pNext->m_pnext;
delete pNext;
pNext = nullptr;
}
// 链表只有一个节点
else if(*pListHead == pToBeDeleted){
delete pToBeDeleted;
pToBeDeleted = nullptr;
*pListHead = nullptr;
}
// 链表中有多个节点,删除尾节点
else{
ListNode * pNext = *pListHead;
while(pNext->m_pnext != pToBeDeleted){
pNext = pNext->m_pnext;
}
// pNext->m_pnext = nullptr;
delete pToBeDeleted;
pToBeDeleted = nullptr;
}
}
题目二:删除链表中重复的节点
在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5
示例1
输入
{1,2,3,3,4,4,5}
返回值
{1,2,5}
代码实现:
- 新建一个节点,防止头结点要被删除
- pre 用来删除 cur节点
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};
*/
class Solution {
public:
ListNode* deleteDuplication(ListNode* pHead)
{
if(pHead == nullptr || pHead->next == nullptr) return pHead;
ListNode * root = new ListNode(0); // 新建一个节点,防止头结点要被删除
root->next = pHead;
ListNode * pre = root, * 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;
}
}
return root->next;
}
};
如有不同见解,欢迎留言讨论~~~