题目
分别实现两个函数,一个可以删除单链表中倒数第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;
}