用O(1)的时间复杂度删除单链表中的某个节点

简介: 给定链表的头指针和一个结点指针,在O(1)时间删除该结点。链表结点的定义如下: struct ListNode { int m_nKey; ListNode* m_pNext; }; 函数的声明如下: void DeleteNode(ListNode* pListHead, ListNode* pToBeDeleted); 这是一道广为流传的Google面试题,考察我们对链表的操作和时间复杂度的了解,咋一看这道题还想不出什么较好的解法,但人家把题出在这,肯定是有解法的。

给定链表的头指针和一个结点指针,在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 }

 

目录
相关文章
|
7月前
|
机器学习/深度学习 Java C++
leetcode-19:删除链表的倒数第N个节点
leetcode-19:删除链表的倒数第N个节点
38 0
leetcode-19:删除链表的倒数第N个节点
|
2月前
【LeetCode 46】450.删除二叉搜索树的节点
【LeetCode 46】450.删除二叉搜索树的节点
21 0
链表遍历,链表查找和统计节点,链表插入新节点,链表删除节点,链表修改指定节点,链表头插法,尾插法总结
链表遍历,链表查找和统计节点,链表插入新节点,链表删除节点,链表修改指定节点,链表头插法,尾插法总结
|
算法
【Leetcode -147.对链表进行插入排序 -237.删除链表中的节点】
【Leetcode -147.对链表进行插入排序 -237.删除链表中的节点】
27 0
剑指offer_链表---删除链表中重复的结点
剑指offer_链表---删除链表中重复的结点
48 0
[leetcode]19 删除链表的倒数第 N 个结点 | 链表模拟
[leetcode]19 删除链表的倒数第 N 个结点 | 链表模拟
71 0
|
机器学习/深度学习
leetcode:19.删除链表的倒数第N个节点
题目已经给出了链表类,此链表比较简单,是个单链表,并且还有一个构造方法。链表是数据结构中比较常见的一种,优点就是增删比较快
53 0
|
Java C语言 C++
【LeetCode】 19. 删除链表的倒数第N个节点
19.删除链表的倒数第N个节点
114 0
【LeetCode】 19. 删除链表的倒数第N个节点
leetcode 450删除二叉搜索树中的节点
leetcode 450删除二叉搜索树中的节点
76 0
leetcode 450删除二叉搜索树中的节点
leetcode 19 删除链表的倒数第n个节点
leetcode 19 删除链表的倒数第n个节点
52 0
leetcode 19 删除链表的倒数第n个节点