日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

剑指offer--在O(1)时间内删除链表结点

發(fā)布時間:2023/12/10 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 剑指offer--在O(1)时间内删除链表结点 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

記錄來自《劍指offer》上的算法題。

題目如下:

給定單向鏈表的頭指針和一個結(jié)點(diǎn)指針,定義一個函數(shù)在O(1)時間刪除該結(jié)點(diǎn)。

結(jié)點(diǎn)定義如下:

struct ListNode{int m_nValue;ListNode* m_pNext; };

最常規(guī)的刪除鏈表結(jié)點(diǎn)方法是從頭結(jié)點(diǎn)開始遍歷,然后找到要刪除結(jié)點(diǎn)的前一個結(jié)點(diǎn),讓它指向要刪除結(jié)點(diǎn)的下一個結(jié)點(diǎn),但是這種做法的時間是O(n),而現(xiàn)在要求時間是O(1),所以就必須換一種方法,解法如下:

// 在O(1)時間內(nèi)刪除給定結(jié)點(diǎn)void DeleteNode(ListNode** pListHead, ListNode* pToBeDeleted){if (!pListHead || !pToBeDeleted)return;if (pToBeDeleted->m_pNext != NULL){// 要刪除的結(jié)點(diǎn)不是尾結(jié)點(diǎn)ListNode* pNext = pToBeDeleted->m_pNext;pToBeDeleted->m_nValue = pNext->m_nValue;pToBeDeleted->m_pNext = pNext->m_pNext;delete pNext;pNext = NULL;}else if (*pListHead == pToBeDeleted){// 鏈表只有一個結(jié)點(diǎn),刪除頭結(jié)點(diǎn),也就是尾結(jié)點(diǎn)delete pToBeDeleted;pToBeDeleted = NULL;*pListHead = NULL;}else{// 鏈表有多個結(jié)點(diǎn),刪除尾結(jié)點(diǎn),采取從頭開始遍歷ListNode* pNode = *pListHead;while (pNode->m_pNext != pToBeDeleted){pNode = pNode->m_pNext;}pNode->m_pNext = NULL;delete pToBeDeleted;pToBeDeleted = NULL;}}

新解法的思路是將待刪除結(jié)點(diǎn)i的下一個結(jié)點(diǎn)j直接覆蓋在要刪除的結(jié)點(diǎn)上,然后再將結(jié)點(diǎn)j刪除,這樣就不需要找到結(jié)點(diǎn)i的前一個結(jié)點(diǎn)了。當(dāng)然,這是一般情況,如果待刪除結(jié)點(diǎn)是一個尾結(jié)點(diǎn),是有多個結(jié)點(diǎn)的鏈表的尾結(jié)點(diǎn),那么就只能采用最常規(guī)的辦法,從頭開始遍歷,但是前面n-1個非尾結(jié)點(diǎn)的時間復(fù)雜度是O(1),所以總的平均時間復(fù)雜度是[(n-1)*O(1) + O(n)]/n,結(jié)果還是O(1)。

測試代碼如下:

// 在鏈表結(jié)尾插入一個結(jié)點(diǎn)void AddToTail(ListNode** pHead, int value){ListNode* pNew = new ListNode();pNew->m_nValue = value;pNew->m_pNext = NULL;if (*pHead == NULL){*pHead = pNew;}else{ListNode* pNode = *pHead;while (pNode->m_pNext != NULL)pNode = pNode->m_pNext;pNode->m_pNext = pNew;}}// 輸出鏈表void printList(ListNode* pHead){ListNode* p = pHead;if (!p)cout << "List is empty!\n";while (p != NULL){cout << p->m_nValue;if (p->m_pNext == NULL)cout << "\n";else{cout << ", ";}p = p->m_pNext;}}// 測試int main(void){ListNode* t = NULL;for (int i = 0; i < 10; i++)AddToTail(&t, i);cout << "List1:\n";printList(t);// 刪除多個結(jié)點(diǎn)鏈表中的一個結(jié)點(diǎn)ListNode* pNode1 = t->m_pNext;DeleteNode(&t, pNode1);printList(t);// 刪除多個結(jié)點(diǎn)鏈表中的頭結(jié)點(diǎn)ListNode* pNode2 = t;DeleteNode(&t, pNode2);printList(t);// 刪除多個結(jié)點(diǎn)鏈表中的尾結(jié)點(diǎn)ListNode* pNode3 = t;while (pNode3->m_pNext != NULL)pNode3 = pNode3->m_pNext;DeleteNode(&t, pNode3);printList(t);// 從只有一個結(jié)點(diǎn)的鏈表中刪除唯一的結(jié)點(diǎn)ListNode* t2 = NULL;AddToTail(&t2, 2);cout << "List2:";printList(t2);DeleteNode(&t2, t2);printList(t2);// 指向鏈表頭結(jié)點(diǎn)指針的是NULL指針DeleteNode(&t2, t2);// 指向要刪除結(jié)點(diǎn)的是NULL指針pNode3 = NULL;DeleteNode(&t, pNode3);system("pause");return 0;}

更完整的例子可以查看我的Github。

總結(jié)

以上是生活随笔為你收集整理的剑指offer--在O(1)时间内删除链表结点的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。