逆置单链表及求链表倒数第k个结点——题集(二)
今天分享一下两道练习题,即逆置单链表以及求链表倒数第k个结点,要求时间复杂度为O(1)。
首先分享一下逆置单链表的代码和运行界面。单链表分为带头结点的单链表和不带头结点的单链表。
源代码如下:
#include<iostream>
using namespace std;
//逆置/反转单链表,要求只能遍历一次链表
struct ListNode{
int val;
ListNode* next;
ListNode(int _val)
:val(_val)
,next(NULL)
{}
};
ListNode* reverse(ListNode* l1){//带头结点
ListNode* head = l1;
if(l1->next==NULL) return head;
l1=l1->next;
ListNode* tail = l1;
if(l1->next==NULL) return head;
l1=l1->next;
tail->next=NULL;//逆置后的最后一个结点next置空//********
while(l1->next != NULL){
ListNode* next=l1->next;
l1->next = tail;
tail=l1;
l1=next;
}
l1->next=tail;//最后一个结点与倒数第二个结点链接
head->next = l1;//把最后一个结点给头结点
return head;
}
ListNode* reverse1(ListNode* l1){//不带头结点
ListNode* head = l1;
ListNode* tail = l1;
if(l1->next==NULL) return head;
l1=l1->next;
tail->next=NULL;//逆置后的最后一个结点next置空//********
while(l1->next != NULL){
ListNode* next=l1->next;
l1->next = tail;
tail=l1;
l1=next;
}
l1->next=tail;//最后一个结点与倒数第二个结点链接
head = l1;//让原链表的最后一个结点变成头结点
return head;
}
void Printf(ListNode* l1){//打印
while(l1!=NULL){
cout<<l1->val<<" ";
l1=l1->next;
}
printf("\n");
}
void Listtest(){
ListNode l0(NULL);
ListNode l1(1);
ListNode l2(2);
ListNode l3(3);
ListNode l4(4);
ListNode l5(11);
l0.next = &l1;
l1.next = &l2;
l2.next = &l3;
l3.next = &l4;
l4.next = &l5;
cout<<"逆置/反转带头结点的单链表,要求只能遍历一次链表。"<<endl;
cout<<"带头结点的单链表l1: ";
Printf(l0.next);
ListNode* tmp = reverse(&l0);
cout<<"逆置后的单链表: ";
Printf(tmp->next);
}
void Listtest1(){
ListNode l1(1);
ListNode l2(2);
ListNode l3(3);
ListNode l4(4);
ListNode l5(11);
l1.next = &l2;
l2.next = &l3;
l3.next = &l4;
l4.next = &l5;
cout<<"逆置/反转不带头结点的单链表,要求只能遍历一次链表。"<<endl;
cout<<"不带头结点的单链表l1: ";
Printf(&l1);
ListNode* tmp = reverse1(&l1);
cout<<"逆置后的单链表: ";
Printf(tmp);
}
int main(){
Listtest();//带头结点的链表逆置//7.14//逆置/反转单链表+查找单链表的倒数第k个节点,要求只能遍历一次链表
cout<<endl<<"******************************"<<endl<<endl;
Listtest1();//带头结点的链表逆置
cout<<"******************************"<<endl;
system("pause");
return 0;
}
运行界面
其次是求链表的倒数第k个结点的源代码和运行界面。
源代码如下:
#include<iostream>
using namespace std;
//查找单链表的倒数第k个节点,要求只能遍历一次链表
struct ListNode{
int val;
ListNode* next;
ListNode(int _val)
:val(_val)
,next(NULL)
{}
};
ListNode* FindK(ListNode* l1,int k){//类快慢指针
ListNode* point=l1;
if(l1 == NULL || k==0)return NULL;
int num=1;
while(l1->next != NULL){
if(num < k){
num++;
l1 = l1->next;
continue;
}
break;
}
if(num < k)return NULL;//链表长度小于k
while(l1->next != NULL){
num++;
point=point->next;
l1=l1->next;
}
return point;
}
void Listtest(){
ListNode l1(1);
ListNode l2(2);
ListNode l3(3);
ListNode l4(4);
ListNode l5(11);
l1.next = &l2;
l2.next = &l3;
l3.next = &l4;
l4.next = &l5;
cout<<"查找单链表的倒数第k个节点,要求只能遍历一次链表。"<<endl;
cout<<"不带头结点的单链表l1: ";
Printf(&l1);
ListNode* prc = FindK(&l1, 0);
cout<<"FindK(&l1, 0):";
if(prc!=NULL)
cout<<prc->val<<endl;
else
cout<<"为NULL,找不到。"<<endl;
prc = FindK(&l1, 2);
cout<<"FindK(&l1, 2):";
if(prc!=NULL)
cout<<prc->val<<endl;
else
cout<<"为NULL,找不到。"<<endl;
prc = FindK(&l1, 4);
cout<<"FindK(&l1, 4):";
if(prc!=NULL)
cout<<prc->val<<endl;
else
cout<<"为NULL,找不到。"<<endl;
prc = FindK(&l1, 8);
cout<<"FindK(&l1, 8):";
if(prc!=NULL)
cout<<prc->val<<endl;
else
cout<<"为NULL,找不到。"<<endl;
}
int main(){
Listtest();//查找单链表的倒数第k个节点
system("pause");
return 0;
}
运行界面
分享如上!望各位学的开心!