面试题-----在O(1)时间删除链表结点
2017-03-23 18:19
232 查看
题目要求
给定单链表的头指针和一个结点指针,定义一个函数在O(1)时间删除该结点。题目分析
首先我看到这个题目,还是会惯性思维,认为删除指定结点,不就是要遍历该链表找到该结点,那就是O(n)呀。。。(无力吐槽我的智商)仔细思考一下,该函数已经给了两个已知的参数了,头节点以及待删除结点。知道待删除结点,也就等于知道了该结点的下一个结点。分析到这里,问题似乎可以解决了,删除该结点,即就是释放该结点的空间,断开该结点与它前面以及后面结点的链,看到这里还不明白的话,可以画画图。先考虑最简单的一种情况,如果我们要在图示的这条链表中删除值c所在的结点,那么知道函数中所给的该结点,就可以将该结点的next结点中的值拷贝给该结点,如下图所示,将c覆盖,然后再将要删除的c结点的next指向原来的d结点的下一结点,图中即为尾结点tail。然后再释放图中的d结点。这样就间接的删除了待删除的C结点,此时的时间复杂度为O(1)。 (欢呼,我们做到了。。)
上面的方案似乎是很可行的,但是是不是真的完全正确那?思考一下,1)假如该链表中就只有一个头结点,上述方案就不可行了,若恰好待删除结点是头结点,那么正好我们可以碰巧删除它,并且记得最后一定要将头结点置空;2)假如链表有头有尾,我们要删除尾结点呐,此时也就只能遍历整个链表找到该结点并删除,时间复杂度为O(n)。
考虑到这里,以为要大功告成了,然而并没有。有没有考虑过对整个函数的思考过程完全建立在一种理想的情况下,那就是我们天真的以为要删除的结点在我们的链表里,所以我们是不是应该首先判断该结点有没有在链表中。但是问题又来了(心好累),查找结点必然是要遍历该链表,时间复杂度必定为O(n),看来这条路我们无法对它做出什么优化了,所以为了完成该题目,只能假设用户输入的待删除结点确确实实在我们的链表中,这个责任就交给该函数的调用者吧。
综上核心代码:
void DeleteNode(NODE **head,NODE *ToBeDelete) { if(head == NULL || ToBeDelete == NULL) return; if(ToBeDelete->next != NULL) { NODE *tmp = ToBeDelete->next; ToBeDelete->data = tmp->data; ToBeDelete->next = tmp->next; delete tmp; tmp = NULL; } else if(ToBeDelete == *head) { delete ToBeDelete; ToBeDelete = NULL; *head = NULL; } else { NODE *tmp = *head; while (tmp != ToBeDelete) { tmp = tmp->next; } tmp->next = NULL; delete ToBeDelete; ToBeDelete = NULL; } }
做不到完美,也要做到近似完美。总体的时间复杂度为【O(N)*(N-1)+O(n)*1】/n,结果为O(n).
总结
连自己都看不太懂并且无法说服自己的代码,还怎么给别人看。我觉得优秀的编程就是写出来的程序能很容易的读懂,所以努力喽相关文章推荐
- (剑指Offer)面试题13:在O(1)时间内删除链表结点
- 面试题13:在O(1)时间内删除链表结点
- 面试题13:在O(1)时间内删除链表结点
- 【面试题013】在O(1)时间删除链表结点
- 剑指offer--面试题13:在O(1)时间删除链表结点--Java实现
- 剑指Offer面试题:12.在O(1)时间删除链表结点
- 剑指offer--面试题13:在O(1)时间删除链表结点
- [剑指offer][面试题13]在O(1)时间删除链表结点
- 程序员面试题精选100题(33)-在O(1)时间删除链表结点[数据结构]
- 面试题13:在O(1)时间删除链表结点
- 面试题13:在O(1)时间删除链表结点
- 【面试题十三】在O(1)时间删除链表结点
- [经典面试题]在O(1)时间删除链表结点
- 面试题13—在O(1)时间删除链表结点
- P99、面试题13:在o(1)时间删除链表结点
- 剑指offer算法题之单链表的删除结点操作--面试题13:在O(1)时间删除链表结点
- 【剑指Offer】面试题13:在O(1)时间删除链表结点
- 面试题13 在o(1)时间删除链表的给定结点
- 《剑指offer》(面试题13):在O(1)时间删除链表结点
- 剑指offer 面试题13 在o(1)时间删除链表结点