在單鏈表和雙鏈表中刪除倒數第K個節點
阿新 • • 發佈:2018-11-20
題目
分別實現兩個函式,一個可以刪除單鏈表中倒數第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;
}