面试题18(一):在O(1)时间删除链表结点
// 面试题18(一):在O(1)时间删除链表结点
// 题目:给定单向链表的头指针和一个结点指针,定义一个函数在O(1)时间删除该
// 结点。链表结点与函数的定义如下:
// struct ListNode{
// int m_nValue;
// ListNode* m_pNext;
// };
// void deleteNode(ListNode** pListHead,ListNode* pToBeDeleted);
解题思路:
这是目前为止,唯一一道,我不看书就知道怎么做的题。
正常从头遍历的话,很明显时间复杂度是O(n),但是他把目标结点给出来了,这就好办了。
直接用目标节点下一个的m_nValue覆盖目标结点,然后删除目标结点就好了。
打开书一看,啊哈哈哈,果然是这个思路啊,就是作者考虑的比我周到多了。
首先,如果目标节点不是尾结点,直接用下一个节点覆盖目标节点,然后删除下一个结点。
如果目标节点就是尾结点(也是头结点),删除头结点。
如果目标节点就是尾结点(不是头结点,链表有多个结点),那么只能从头结点开始遍历了。
然后分析一下时间复杂度,一个有n个结点的链表,非尾结点有n-1个,直接删除后边的结点,时间复杂度为(n-1)*O(1)。
尾节点有一个,时间复杂度为1*O(n),平均一下就是O(1),满足题目的要求。
c/c++:
void DeleteNode(ListNode** pListHead, ListNode* pToBeDeleted) { //参数校验 if (pListHead == nullptr || pToBeDeleted == nullptr) return; //目标结点不位于尾结点,用下一个节点覆盖目标结点 if (pToBeDeleted->m_pNext != nullptr) { ListNode* pNode = pToBeDeleted->m_pNext; pToBeDeleted->m_nValue = pNode->m_nValue; pToBeDeleted->m_pNext = pNode->m_pNext; delete pNode; pNode = nullptr; } //目标节点与头结点重合,链表只有一个结点 else if (*pListHead == pToBeDeleted) { delete pToBeDeleted; pToBeDeleted = nullptr; *pListHead = nullptr; } //链表有多个节点,且目标结点是尾节点 else { ListNode* pNode = *pListHead; while (pNode->m_pNext != pToBeDeleted) { pNode = pNode->m_pNext; } pNode->m_pNext = nullptr; delete pToBeDeleted; pToBeDeleted = nullptr; } return; }