1. 程式人生 > >在單鏈表和雙鏈表中刪除倒數第K個節點

在單鏈表和雙鏈表中刪除倒數第K個節點

題目

分別實現兩個函式,一個可以刪除單鏈表中倒數第K個節點,另一個可以刪除雙鏈表中倒數第K個節點。

要求

如果連結串列長度為n,則要時間複雜度達到O(N),額外空間複雜度達到O(1).

思路

一種方法是設定快慢指標,快指標先走k步,此時慢指標從頭開始走,兩者同時開始走,當快指標走到尾時,慢指標走到倒數第K個節點,刪除當前慢指標的節點,(問題是要記錄前後兩個節點)單鏈表和雙鏈表兩種情況。

書中給出的方法是根據k值得變化來進行刪除操作,連結串列從頭開始,每移動一步,k值減1,最後,若k=0:刪除頭節點;若k>0,不刪除;若k<0,當k=0時為倒數第k個節點;之後再次從頭節點開始,k每步自增1,等於0時為倒數k個節點的前一個節點。
在雙鏈表中執行刪除操作時注意prev指標的指向問題即可,不再對雙鏈表進行測試。

以下程式碼根據上面兩個思路均進行了測試。

程式碼

#include<iostream>
using namespace std;

struct singleList {
	int value;
	singleList* next;
	singleList(int val)
	{
		value = val;
	}
};

struct doubleList {
	int value;
	doubleList* next;
	doubleList* prev;
	doubleList(int val)
	{
		value = val;
	}
};

void delLastKSingle1
(singleList* head, int k) { if (head == NULL || k <= 0) return; singleList* rawHead = new singleList(-1); rawHead->next = head; singleList* fast = head; singleList* slow = head; for (int i = 0; i < k; i++) { fast = fast->next; } singleList* prev = rawHead; while (fast != NULL
) { fast = fast->next; slow = slow->next; prev = prev->next; } singleList* pNode = slow; prev->next = slow->next; delete pNode; } singleList* delLastKSingle(singleList* head, int k) { if (head == NULL || k <= 0) return head; singleList* cur = head; while (cur != NULL) { k--; cur = cur->next; } if (k == 0) head = head->next; if (k < 0) { cur = head; while ((k++) != 0) cur = cur->next; cur->next = cur->next->next; } return head; } singleList* createSingle(int* in, int len) { singleList* head = new singleList(in[0]); singleList* p = head; for (int i = 1; i < len; i++) { singleList* node = new singleList(in[i]); p->next = node; p = p->next; } p->next = NULL; return head; } void printS(singleList* head) { cout << "print node of list:" << endl; while (head != NULL) { cout << head->value << " "; head = head->next; } cout << endl; } int main() { int input[] = { 1, 2, 3, 4, 5 }; int len = 5; singleList* headS = createSingle(input, len); int k = 2; //delLastKSingle1(headS, k); delLastKSingle1(headS, k); printS(headS); getchar(); return 0; }