lintcode:372.在O(1)时间复杂度删除链表节点

2016年10月14日00:19:41
 

给定一个单链表中的一个等待被删除的节点(非表头或表尾)。请在在O(1)时间复杂度删除该链表节点。

您在真实的面试中是否遇到过这个题? 
Yes
样例
给定 1->2->3->4,和节点 3,删除 3 之后,链表应该变为1->2->4
 
/**
 * 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->val = node->next->val;
     node->next = node->next->next;
     delete(node->next);     // 出现奇异,因为此时的node指向两个结点
   }
};
 
注:没有考虑如果node值由多个或者node->next为空,则有可能出现0覆盖掉
---------2016年10月14日00:33:06
本以为是没考虑上面注释的问题,参考了网上的博客1 和博客2之后,尤其是博客1,发现其实是delete的对象---node->next出现了奇异,这个细节出现了问题,也暴露了自己对链表的基本操作的不熟悉,引以为戒,

 
如:

 

Wrong Answer

总耗时: 5 ms
33% 数据通过测试.
输入
999->12412->123->9->123->null, 123
输出
999->12412->9->0->null
    
解决办法:
     重新申请一个结点p指向node的next之后,进行操作,顺利的通过了测试
 
 
void deleteNode(ListNode *node) {
 // write your code here
 
    ListNode *p = node->next;
    node->val = p->val;
    node->next = p->next;
    delete p;
}
 

 
博客2亦有值得参考的内容,如下:
 
 
给定链表的头指针和一个结点指针,在O(1)时间删除该结点。链表结点的定义如下:
 
struct ListNode
{
      int        m_nKey;
      ListNode*  m_pNext;
};
 
函数的声明如下:
 
void DeleteNode(ListNode* pListHead, ListNode* pToBeDeleted);
 
这是一道广为流传的Google面试题,考察我们对链表的操作和时间复杂度的了解,咋一看这道题还想不出什么较好的解法,但人家把题出在这,肯定是有解法的。一般单链表删除某个节点,需要知道删除节点的前一个节点,则需要O(n)的遍历时间,显然常规思路是不行的。在仔细看题目,换一种思路,既然不能在O(1)得到删除节点的前一个元素,但我们可以轻松得到后一个元素,这样,我们何不把后一个元素赋值给待删除节点,这样也就相当于是删除了当前元素。可见,该方法可行,但如果待删除节点为最后一个节点,则不能按照以上思路,没有办法,只能按照常规方法遍历,时间复杂度为O(n),是不是不符合题目要求呢?可能很多人在这就会怀疑自己的思考,从而放弃这种思路,最后可能放弃这道题,这就是这道面试题有意思的地方,虽看简单,但是考察了大家的分析判断能力,是否拥有强大的心理,充分自信。其实我们分析一下,仍然是满足题目要求的,如果删除节点为前面的n-1个节点,则时间复杂度为O(1),只有删除节点为最后一个时,时间复杂度才为O(n),所以平均的时间复杂度为:(O(1) * (n-1) + O(n))/n = O(1);仍然为O(1).下面见代码:
 
 1 /* Delete a node in a list with O(1)
 2  * input:    pListHead - the head of list
 3  *            pToBeDeleted - the node to be deleted
 4  */
 5
 6 struct  ListNode
 7 {
 8     int            m_nKey;
 9     ListNode*    m_pNext;
10 };
11
12 void DeleteNode(ListNode *pListHead, ListNode *pToBeDeleted)
13 {
14     if (!pListHead || !pToBeDeleted)
15         return;
16
17     if (pToBeDeleted->m_pNext != NULL) {
18         ListNode *pNext = pToBeDeleted->m_pNext;
19         pToBeDeleted->m_pNext = pNext->m_pNext;
20         pToBeDeleted->m_nKey = pNext->m_nKey;
21
22         delete pNext;
23         pNext = NULL;
24     }
25     else { //待删除节点为尾节点
26         ListNode *pTemp = pListHead;
27         while(pTemp->m_pNext != pToBeDeleted)
28             pTemp = pTemp->m_pNext;
29         pTemp->m_pNext = NULL;
30
31         delete pToBeDeleted;
32         pToBeDeleted = NULL;
33     }
34 }
 
 
 
 
 
 
 
 
posted @ 2016-10-14 00:47  第五个季节的心情  阅读(152)  评论(0)    收藏  举报