题目:
提示:由于优快云不支持Leetcode将图片转化为类似ppt形式的界面,笔者推荐去LeetCode看本题解
LeetCode题解链接:剑指offer 18.删除链表的节点
给定单向链表的头指针和一个要删除的节点的值,定义一个函数删除该节点。返回删除后的链表的头节点。
示例1:
输入:head = [4,5,1,9],node=5
输出:[4,1,9]
示例2:
输入:head = [4,5,1,9],node=1
输出:[4,5,9]
解题思路
假设我们要删除链表中的cur节点,如下图所示
要删除cur,我们只需要找到cur节点的前一个节点prev,和cur的下一个节点Next,然后将prev的next指针指向Next,即prev->next=Next。这样链表在之后的使用过程中,将不再遍历cur节点,相当于将cur节点删除出链表。
一般来说,在删除节点的过程中,如果链表头结点head,也可能被删除的话,为了方便,我们就得人为定义一个head结点的前一个节点,也就是虚拟头结点dummy,这样链表中所有的结点均可一视同仁,进行相同的操作。
上述两种删除操作涉及两种链表的操作方式:
1. 直接对链表进行操作;
2. 设计虚拟头结点(哑结点)dummy=new ListNode(-1,head)再对链表进行操作;
由于本题删除的节点,可能为头结点,而链表本身,头结点没有前一个节点prev,所以为了方便编写代码,我们使用方法2,定义一个虚拟头结点dummy,也叫哑结点,dummy使用方法如下所示:
ListNode* dummy=new ListNode(-1,head);//哑结点的值随意定义,只要使用者能分辨出哑结点即可。
ListNode* cur=dummy;
//利用cur进行链表遍历,并对链表进行操作
return dummy->next; //返回内容为操作完成之后的链表,该链表不包括哑结点
方法1相比方法2,差别不大,如果初学者无法理解方法1,请看题解83.删除排序链表中的重复元素
代码
class Solution {
public:
ListNode* deleteNode(ListNode* head, int val) {
ListNode* dummy=new ListNode(-1,head);
ListNode* cur=dummy;
while(cur->next)//由于即使head为空,cur初始值也不为空,所以该循环不会报错。
{
if(cur->next->val==val)
{
cur->next=cur->next->next;
/*找到需要删除的节点后,进行常规删除操作。
*此时cur->next需要被删除,所以只需改变cur节点的next指针即可。
*/
break;
//只删除一个节点,找到删除该节点之后,无需再遍历,节省时间
}
cur=cur->next;//cur节点要不断往后走,才能进行链表的遍历。
}
return dummy->next;
}
};
算法复杂度:
由于只进行了链表的一次遍历,时间复杂度为:O(n),空间复杂度为:O(1)。