统一使用结构体
struct ListNode
{
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL){}
};
链表合并
假设 两个链表中数据都是有序链表,将两个链表按从小到大合并
// 链表1
ListNode a(10);
ListNode b(20);
ListNode c(30);
ListNode d(40);
ListNode e(50);
a.next = &b;
b.next = &c;
c.next = &d;
d.next = &e;
ListNode *head = &a;
// 链表2
ListNode a1(19);
ListNode b1(29);
ListNode c1(39);
ListNode d1(49);
ListNode e1(59);
a1.next = &b1;
b1.next = &c1;
c1.next = &d1;
d1.next = &e1;
ListNode *head2 = &a1;
// 打印链表1
while(head)
{
cout << head->val << " " ;
head = head->next;
}
cout << endl;
head = &a;
// 打印链表2
while(head2)
{
cout << head2->val << " " ;
head2 = head2->next;
}
cout << endl;
head2 = &a1;
// 开始准备合并链表
ListNode tmpNode(0); // 设置临时节点
ListNode *new_head = &tmpNode; // 将临时节点作为新链表的头
while(head && head2)
{
// 比较判断那个节点应该追加到临时节点
if(head->val < head2->val)
{
new_head->next = head;
head = head->next;
}
else
{
new_head->next = head2;
head2 = head2->next;
}
new_head = new_head->next;
}
// 判断 两个链表中是否有剩余节点
if(head)
{
new_head->next = head;
}
if(head2)
{
new_head->next = head2;
}
// 到 新链表的头节点位置
new_head = tmpNode.next;
// 打印新链表
while(new_head)
{
cout << new_head->val << " " ;
new_head = new_head->next;
}
cout << endl;
查找两个链表的交点
题干:
1、保护原有链表的结构和数据域
2、尽可能 保证时间复杂度为o(N),空间复杂度为 o(1)
ListNode a(10);
ListNode b(20);
ListNode c(30);
ListNode d(40);
ListNode e(50);
a.next = &b;
b.next = &c;
c.next = &d;
d.next = &e;
ListNode *head = &a;
ListNode a1(19);
ListNode b1(29);
ListNode d1(49);
ListNode e1(59);
a1.next = &b1;
b1.next = &c;
c.next = &d1;
d1.next = &e1;
ListNode *head2 = &a1;
std::set<ListNode *> tmp_set;
while(head)
{
tmp_set.insert(head);
head = head->next;
}
head = &a;
int iIndex = 0;
ListNode *listEqual = nullptr;
while(head2)
{
auto iter = tmp_set.find(head2);
if(iter != tmp_set.end())
{
listEqual = head2;
break;
}
head2 = head2->next;
++iIndex;
}
if(listEqual)
{
cout << "Index: " << iIndex << " Val: " << listEqual->val << " 地址: " << listEqual->next << endl;
}
链表求环
环链表
ListNode a(10);
ListNode b(20);
ListNode c(30);
ListNode d(40);
ListNode e(50);
a.next = &b;
b.next = &c;
c.next = &d;
d.next = &e;
e.next = &b; // 生成环
ListNode *head = &a;
1、通过 set 容器求环
std::set<ListNode *> tmp_set;
int iIndex = 0;
ListNode *listEqual = nullptr;
while(head)
{
auto iter = tmp_set.find(head);
if(iter != tmp_set.end())
{
listEqual = head; // 环的起始节点
break;
}
tmp_set.insert(head);
head = head->next;
++iIndex;
}
if(listEqual)
{
cout << "Index: " << iIndex << " Val: " << listEqual->val << " 地址: " << listEqual->next << endl;
}
2、通过快慢指针求环
原理
ListNode *fastHead = head;
ListNode *normalHead = head;
ListNode *listMeet = nullptr;
while(head)
{
fastHead = fastHead->next;
normalHead = normalHead->next;
if(!fastHead)
{
break;
}
fastHead = fastHead->next;
if(normalHead == fastHead)
{
listMeet = fastHead;
break;
}
}
while (head && listMeet)
{
if(head == listMeet)
{
cout << " Val: " << head->val << " 地址: " << head->next << endl;
break;
}
listMeet = listMeet->next;
head = head->next;
}