逆置單鏈表及求鏈表倒數第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;
}
運行界面
分享如上!望各位學的開心!