1.描述
给定一个单链表中的一个等待被删除的节点(非表头或表尾)。请在在O(1)时间复杂度删除该链表节点。
样例
给定 1->2->3->4
,和节点 3
,删除 3 之后,链表应该变为 1->2->4
。
2.分析
按照一般的思路,删除一个节点node首先需要找到他所在的位置,让node的上一个节点直接指向node的下一个节点,
空过node,也就是让node->perior的next指向node->next,但这样做首先需要知道node->perior(这在单链表中不好实现),
并且这样做是o(n)的算法,题目要求为o(1)时间复杂度。在上面的分析中,我们发现只要让node的下一个节点取代node的位置
就相当于空过了node让node的前一个节点指向后一个节点,因此有了最简单的一句代码*node=*(node->next);
3.代码:
/**
* Definition of ListNode
* class ListNode {
* public:
* int val;
* ListNode *next;
* ListNode(int val) {
* this->val = val;
* this->next = NULL;
* }
* }
*/
class Solution {
public:
/**
* @param node: a node in the list should be deleted
* @return: nothing
*/
void deleteNode(ListNode *node) {
// write your code here
*node=*(node->next);
}
};
4.总结
下面两种情况分别对应了两种错误。把红字部分替换为下面的绿字部分。
(1)
node->val=node->next->val;
node=node->next;
乍一看似乎没有什么区别,所存数据val给了,指针也给了,但事实上这段代码运行是wrong answer
因为从根本上看,只是把node的下一个节点所存数据赋值给了node节点,同时让node指针指向下一个节点,
故此没有达到删除node节点的目的。
(2)
node=node->next;
node->val=node->next->val;
这两句和上面两句看起来也有些相似,只是变了变位置,但如果运行出来结果就不是wrong answer
而是run time error了。
因此我们发现要删除某个节点最重要的还是找到他所在的地址,*node才是真正对现在node所在的空间
进行操作。