一、链表逆置
1、题目、已知一链表,求将其逆置后的链表
2、代码实现
#include<iostream>
using namespace std;
struct ListNode
{
int val;
ListNode *next;
};
class solution
{
public:
ListNode* reverseList(ListNode* head)
{
ListNode* newhead =NULL ;
while( head )
{
ListNode* pNode = head->next ;
head->next = newhead;
newhead = head;
head = pNode;
}
return newhead;
}
};
int main()
{
ListNode a;
ListNode b;
ListNode c;
ListNode d;
ListNode e;
ListNode f;
ListNode g;
a.val =1;
b.val =2;
c.val =3;
d.val =4;
e.val =5;
f.val =6;
g.val =7;
a.next =&b;
b.next =&c;
c.next =&d;
d.next =&e;
e.next =&f;
f.next =&g;
g.next =NULL;
solution solve;
printf("原链表长度为:");
ListNode*phead = &a;
while(phead)
{
printf("%d ",phead->val );
phead = phead->next ;
}
printf("\n逆序后链表为:");
phead = solve.reverseList (&a);
while(phead)
{
printf("%d ",phead->val );
phead = phead->next ;
}
return 0;
}
3、程序结果
1.2.1、题目:已知一链表,将从m到n之间的节点逆置,并打印逆置后链表
1.2.2程序实现
#include<iostream>
using namespace std;
struct ListNode
{
int val;
ListNode *next;
};
class solution
{
public:
ListNode* reverseList(ListNode* head,int m,int n)
{
int change_len = n - m +1;
ListNode* result = head;
ListNode* pre = NULL;
while(head && --m)
{
pre = head;
head = head->next ;
}
ListNode* newhead = NULL;
ListNode* modify_list_tail = head;
while( head && change_len)
{
ListNode* pNode = head->next ;
head->next = newhead;
newhead = head;
head = pNode;
change_len--;
}
modify_list_tail->next = head;
if(pre)
{
pre->next = newhead;
}
return result;
}
};
int main()
{
ListNode a;
ListNode b;
ListNode c;
ListNode d;
ListNode e;
ListNode f;
ListNode g;
a.val =1;
b.val =2;
c.val =3;
d.val =4;
e.val =5;
f.val =6;
g.val =7;
a.next =&b;
b.next =&c;
c.next =&d;
d.next =&e;
e.next =&f;
f.next =&g;
g.next =NULL;
solution solve;
printf("原链表打印为:");
ListNode*phead = &a;
while(phead)
{
printf("%d ",phead->val );
phead = phead->next ;
}
printf("\n逆序后链表为:");
phead = solve.reverseList (&a,3,6);
while(phead)
{
printf("%d ",phead->val );
phead = phead->next ;
}
return 0;
}
1.2.3程序结果
二、求两个链表的交点
2、题目:已知链表A的头节点head1,链表B的节点head2,两个链表相交,求相交节点
2.1.1程序实现
#include<iostream>
#include<set>
using namespace std;
struct ListNode
{
int val;
ListNode *next;
ListNode(int x)
:val(x)
,next(NULL)
{}
};
class solution
{
public:
ListNode* FindTheCrossPoint(ListNode* head1,ListNode* head2)
{
std::set<ListNode*> node_set;
while(head1)
{
node_set.insert(head1);
head1 = head1->next ;
}
while(head2)
{
if( ( node_set.find(head2) )!= node_set.end())
{
return head2;
}
head2 = head2->next ;
}
return NULL;
}
};
void print(ListNode*head)
{
while(head)
{
printf("%d ",head->val );
head = head->next ;
}
}
int main()
{
ListNode a(1);
ListNode b(2);
ListNode c(3);
ListNode d(4);
ListNode e(5);
ListNode f(6);
ListNode g(7);
a.next =&b;
b.next =&c;
c.next =&d;
d.next =NULL;
e.next =&f;
f.next =&g;
g.next =&c;
solution solve;
ListNode*phead1 = &a;
printf("phead1打印为:");
print(phead1);
ListNode* phead2 = &e;
printf("\nphead2打印为:");
print(phead2);
printf("\n相交链表为:");
ListNode* phead = solve.FindTheCrossPoint(phead1,phead2);
print(phead);
return 0;
}
2.1.2程序结果
2.2第二种解法
2.2.1程序实现
#include<iostream>
#include<set>
using namespace std;
struct ListNode
{
int val;
ListNode *next;
ListNode(int x)
:val(x)
,next(NULL)
{}
};
class solution
{
public:
int Length(ListNode* head)
{
int count = 0;
while(head)
{
++count;
head = head->next ;
}
return count;
}
ListNode* Forward(int Long_len ,int Short_len, ListNode* head)
{
int dis = Long_len - Short_len;
while(head && dis)
{
head = head->next ;
--dis;
}
return head;
}
ListNode* FindTheCrossPoint(ListNode* head1,ListNode* head2)
{
int len_head1 = Length(head1);
int len_head2 = Length(head2);
if(len_head1 > len_head2)
{
head1 = Forward(len_head1, len_head2, head1);
}
else
{
head2 = Forward(len_head2,len_head1, head2);
}
while(head1 && head2)
{
if(head1 == head2)
{
return head1;
}
head1 = head1->next ;
head2 = head2->next ;
}
return NULL;
}
};
void print(ListNode*head)
{
while(head)
{
printf("%d ",head->val );
head = head->next ;
}
}
int main()
{
ListNode a(1);
ListNode b(2);
ListNode c(3);
ListNode d(4);
ListNode e(5);
ListNode f(6);
ListNode g(7);
a.next =&b;
b.next =&c;
c.next =&d;
d.next =NULL;
e.next =&f;
f.next =&g;
g.next =&c;
solution solve;
ListNode*phead1 = &a;
printf("phead1打印为:");
print(phead1);
ListNode* phead2 = &e;
printf("\nphead2打印为:");
print(phead2);
printf("\n相交链表为:");
ListNode* phead = solve.FindTheCrossPoint(phead1,phead2);
print(phead);
return 0;
}
2.2.2程序结果
三、链表求环
3.题目:已知链表可能存在环,若有,返回环的起始节点,没有返回NULL
3.1使用STL中set实现
3.1.1程序实现
#include<iostream>
#include<set>
using namespace std;
struct ListNode
{
int val;
ListNode *next;
ListNode(int x)
:val(x)
,next(NULL)
{}
};
class solution
{
public:
ListNode* FindTheCircle(ListNode* head)
{
std::set<ListNode*> node_set;
while(head)
{
if(node_set.find(head)!= node_set.end())
{
head->next =NULL;
return head ;
}
node_set.insert(head);
head = head->next ;
}
return NULL;
}
};
void print(ListNode*head)
{
while(head)
{
printf("%d ",head->val );
head = head->next ;
}
}
int main()
{
ListNode a(1);
ListNode b(2);
ListNode c(3);
ListNode d(4);
ListNode e(5);
ListNode f(6);
ListNode g(7);
a.next =&b;
b.next =&c;
c.next =&d;
d.next =&e;
e.next =&f;
f.next =&g;
g.next =&c;
solution solve;
ListNode*phead1 = &a;
printf("\n环的入口节点为:");
ListNode* head = solve.FindTheCircle(phead1);
print(head);
return 0;
}
3.1.2程序结果
3.2使用快慢指针思想实现
3.2.1程序实现
#include<iostream>
using namespace std;
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
ListNode *fast = head;
ListNode *slow = head;
ListNode *meet = NULL;
while(fast){
slow = slow->next;
fast = fast->next;
if (!fast){
return NULL;
}
fast = fast->next;
if (fast == slow){
meet = fast;
break;
}
}
if (meet == NULL){
return NULL;
}
while(head && meet){
if (head == meet){
return head;
}
head = head->next;
meet = meet->next;
}
return NULL;
}
};
int main(){
ListNode a(1);
ListNode b(2);
ListNode c(3);
ListNode d(4);
ListNode e(5);
ListNode f(6);
ListNode g(7);
a.next = &b;
b.next = &c;
c.next = &d;
d.next = &e;
e.next = &f;
f.next = &g;
g.next = &c;
Solution solve;
ListNode *node = solve.detectCycle(&a);
if (node){
printf("%d\n", node->val);
}
else{
printf("NULL\n");
}
return 0;
}
3.2.2程序结果
四、链表划分
4.1题目:已知链表的头指针head与数值X,将所有小于X的数,全部放在大于X或者等于X的节点前,并且保持这些节点的原来相对位置。
4.1.2程序实现
#include<iostream>
using namespace std;
struct ListNode
{
int val;
ListNode* next;
ListNode(int x)
:val(x)
,next(NULL)
{}
};
class solution
{
public:
ListNode* partion(ListNode* head,int x)
{
ListNode less_head(0);//注意
ListNode more_head(0);
ListNode* less_ptr = &less_head;//注意
ListNode* more_ptr = &more_head;
while(head)
{
if(head->val >= x )
{
more_ptr->next = head;
more_ptr = head;
}
else
{
less_ptr->next = head;
less_ptr = head;
}
head = head->next ;
}
less_ptr->next = more_head.next ;
more_ptr->next = NULL;
return less_head.next ;
}
};
void print(ListNode*head)
{
while(head)
{
printf("%d ",head->val );
head = head->next ;
}
}
int main()
{
ListNode a(1);
ListNode b(4);
ListNode c(3);
ListNode d(2);
ListNode e(5);
ListNode f(2);
a.next = &b;
b.next = &c;
c.next = &d;
d.next = &e;
e.next = &f;
f.next = NULL;
printf("原链表打印为:");
print(&a);
solution solve;
printf("\n链表划分应为:");
ListNode*head = solve.partion(&a,3);
print(head);
return 0;
}
4.1.2程序结果
五、复杂链表的深度拷贝
5.1题目:已知一个复杂链表,每个节点有两个指针,一个指向下一个节点,另一个是指向本链表的任意一个节点的随机指针,求这个链表的深度拷贝
5.2程序实现
#include<iostream>
#include<map>
#include<vector>
using namespace std;
struct ListNode
{
int val;
ListNode* next;
ListNode* random;
ListNode(int x)
:val(x)
,next(NULL)
,random(NULL)
{}
};
class solution
{
public:
ListNode* copyRandom(ListNode* head)
{
std::map<ListNode*,int> node_map;
std::vector<ListNode*> node_vec;
ListNode* ptr = head;
int i = 0;
while(ptr)//将节点装入vector中,并使得map形成地址映射
{
node_vec.push_back(new ListNode(ptr->val));
node_map[ptr] = i;
ptr = ptr->next ;
i++;
}
node_vec.push_back (0);
ptr = head;//再次遍历链表,
i = 0;
while(ptr)
{
node_vec[i] ->next = node_vec[i+1];//将节点链接起来
if(ptr->random )//将指针指好
{
int id = node_map[ptr->random ];
node_vec[i]->random = node_vec[id];
}
ptr = ptr->next ;
i++;
}
return node_vec[0];
}
};
void print(ListNode*head)
{
while(head)
{
printf("%d ",head->val );
head = head->next ;
}
}
int main(){
ListNode a(1);
ListNode b(2);
ListNode c(3);
ListNode d(4);
ListNode e(5);
a.next = &b;
b.next = &c;
c.next = &d;
d.next = &e;
a.random = &c;
b.random = &d;
c.random = &c;
e.random = &d;
solution solve;
ListNode *head = solve.copyRandom(&a);
while(head)
{
printf("val = %d ", head->val);
if (head->random)
{
printf("rand = %d\n", head->random->val);
}
else
{
printf("rand = NULL\n");
}
head = head->next;
}
return 0;
}
5.3程序结果
六、两个链表的合并
6.1题目:已知两个已排序头节点指针head1,head2,将这两个链表合并,使得合并后链表也是有序的,并且返回合并后的头节点
6.2程序实现
#include<iostream>
using namespace std;
struct ListNode
{
int val;
ListNode *next;
ListNode(int x)
:val(x)
,next(NULL)
{}
};
class solution
{
public:
ListNode* MergeTwoList(ListNode* head1,ListNode* head2)
{
ListNode temp(0);
ListNode* temp_head = &temp;
while(head1 && head2)
{
if(head1->val < head2->val )
{
temp_head->next = head1;
head1= head1->next ;
}
else
{
temp_head->next = head2;
head2 = head2->next ;
}
temp_head = temp_head->next ;
}
if(head1)
{
temp_head->next = head1;
}
if(head2)
{
temp_head->next = head2;
}
return temp.next ;
}
};
void print(ListNode*head)
{
while(head)
{
printf("%d ",head->val );
head = head->next ;
}
}
int main()
{
ListNode a(1);
ListNode b(3);
ListNode c(5);
ListNode d(7);
ListNode e(2);
ListNode f(4);
ListNode g(6);
a.next =&b;
b.next =&c;
c.next =&d;
d.next =NULL;
e.next =&f;
f.next =&g;
g.next =NULL;
solution solve;
ListNode*phead1 = &a;
printf("phead1打印为:");
print(phead1);
ListNode* phead2 = &e;
printf("\nphead2打印为:");
print(phead2);
printf("\n合并后链表为:");
ListNode* phead = solve.MergeTwoList(phead1,phead2);
print(phead);
return 0;
}
6.3程序结果
##七、 k个已排序的链表合并 ##
7.1题目:已知k个已派序链表头节点指针,将这K个链表合并,合并后仍为有序的,返回合并后的头节点
7.1.1利用vector实现,将所有的链表节点都放在vector中,在将vector中的每个节点排序,最后实现
7.1.2程序实现
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
struct ListNode
{
int val;
ListNode *next;
ListNode(int x)
:val(x)
,next(NULL)
{}
};
void print(ListNode*head)
{
while(head)
{
printf("%d ",head->val );
head = head->next ;
}
}
bool cmp(const ListNode *a,const ListNode* b)
{
return a->val <b->val ;
}
int main()
{
ListNode a(1);
ListNode b(3);
ListNode c(5);
ListNode d(7);
ListNode e(2);
ListNode f(4);
ListNode g(6);
ListNode h(8);
ListNode i(9);
ListNode j(11);
ListNode k(10);
ListNode l(15);
ListNode m(17);
ListNode n(19);
a.next =&b;
b.next =&c;
c.next =&d;
d.next =NULL;
e.next =&f;
f.next =&g;
g.next =NULL;
h.next = &i;
i.next = &j;
j.next = NULL;
k.next = &l;
l.next = &m;
m.next =&n;
n.next =NULL;
std::vector<ListNode*> node_vec;
node_vec.push_back(&a);
node_vec.push_back(&b);
node_vec.push_back(&c);
node_vec.push_back(&d);
node_vec.push_back(&e);
node_vec.push_back(&f);
node_vec.push_back(&g);
node_vec.push_back(&h);
node_vec.push_back(&i);
node_vec.push_back(&j);
node_vec.push_back(&k);
node_vec.push_back(&l);
node_vec.push_back(&m);
node_vec.push_back(&n);
std::sort(node_vec.begin(),node_vec.end(),cmp);
ListNode*phead1 = &a;
printf("phead1打印为:");
print(phead1);
ListNode* phead2 = &e;
printf("\nphead2打印为:");
print(phead2);
ListNode*phead3 = &h;
printf("\nphead3打印为:");
print(phead3);
ListNode*phead4 = &k;
printf("\nphead4打印为:");
print(phead4);
printf("\n合并后链表为 :");
for(int i = 0; i<node_vec.size();i++)
{
printf("%d ",node_vec[i]->val );
}
return 0;
}
7.1.2程序结果
7.2.1使用map进行地址映射
7.2.2程序实现
#include <stdio.h>
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
#include <vector>
#include <algorithm>
bool cmp(const ListNode *a, const ListNode *b){
return a->val < b->val;
}
class Solution {
public:
ListNode* mergeKLists(std::vector<ListNode*>& lists) {
std::vector<ListNode *> node_vec;
for (int i = 0; i < lists.size(); i++){
ListNode *head = lists[i];
while(head){
node_vec.push_back(head);
head = head->next;
}
}
if (node_vec.size() == 0){
return NULL;
}
std::sort(node_vec.begin(), node_vec.end(), cmp);
for (int i = 1; i < node_vec.size(); i++){
node_vec[i-1]->next = node_vec[i];
}
node_vec[node_vec.size()-1]->next = NULL;
return node_vec[0];
}
};
int main(){
ListNode a(1);
ListNode b(4);
ListNode c(6);
ListNode d(0);
ListNode e(5);
ListNode f(7);
ListNode g(2);
ListNode h(3);
a.next = &b;
b.next = &c;
d.next = &e;
e.next = &f;
g.next = &h;
Solution solve;
std::vector<ListNode *> lists;
lists.push_back(&a);
lists.push_back(&d);
lists.push_back(&g);
ListNode *head = solve.mergeKLists(lists);
while(head){
printf("%d\n", head->val);
head = head->next;
}
return 0;
}
7.2.3程序结果