#pragma once
#include <vector>
#include <string>
#include <iostream>
using namespace std;
namespace List
{
struct ListNode {
int val;
ListNode* next;
ListNode(int x) : val(x), next(NULL) {}
};
// 打印链表
void PrintList(ListNode* phead, string strFun = "list")
{
printf("%s: ", strFun.c_str());
if (phead == nullptr)
{
printf("is empty.");
}
printf("%d, ", phead->val);
ListNode* pCur = phead->next;
while (pCur != nullptr)
{
printf("%d, ", pCur->val);
pCur = pCur->next;
}
printf("\n");
}
// 创建链表
ListNode* CreateList(const vector<int>& v)
{
ListNode* pHead = nullptr;
if (v.empty())
{
return pHead;
}
pHead = new ListNode(v[0]);
if (pHead == nullptr)
{
return pHead;
}
ListNode* pPre = pHead;
for (int i = 1; i < v.size(); ++i)
{
ListNode* pNew = new ListNode(v[i]);
if (pNew != nullptr)
{
pPre->next = pNew;
pPre = pNew;
}
}
// 同时打印链表
PrintList(pHead, __FUNCTION__);
return pHead;
}
// 反转链表
// 双指针实现
ListNode* ReverseList1(ListNode* pHead)
{
ListNode* pCur = nullptr;
ListNode* pNext = pHead;
while (pNext != nullptr)
{
ListNode* pTemp = pNext->next;
pNext->next = pCur;
pCur = pNext;
pNext = pTemp;
}
pHead = pCur;
// 同时打印链表
PrintList(pHead, __FUNCTION__);
return pHead;
}
// 反转链表
// 递归实现,首先通过递归确定尾端结点,并进行翻转操作,返回代表着我已经将你下一个结点以后的结点都翻转好了,你只需要翻转你和你的下一个结点。
ListNode* ReverseList2(ListNode* pHead)
{
if (pHead == nullptr || pHead->next == nullptr)
return pHead;
// 一直递归到尾结点pRet返回
ListNode* pRet = ReverseList2(pHead->next);
pHead->next->next = pHead;
pHead->next = nullptr;
return pRet;
}
// 分割链表,
// 编写程序以 x 为基准分割链表,使得所有小于 x 的节点排在大于或等于 x 的节点之前。
// 可以只交互节点中的数值
ListNode* PartitionList(ListNode* pHead, int x)
{
ListNode* p1 = pHead;
ListNode* p2 = pHead;
while (p2 != nullptr)
{
if (p2->val < x)
{
// 交换
int temp = p1->val;
p1->val = p2->val;
p2->val = temp;
p1 = p1->next;
}
p2 = p2->next;
}
// 同时打印链表
PrintList(pHead, __FUNCTION__);
return pHead;
}
// 判断两链表相交
// 思想:存在A、B两个链表,其中交点为p,两链表相交长度为c,A链表中p点前的长度为a,B链表中p点前的长度为b,需要满足走过的路程 a+c+b = b+c+a,则会相遇
// 创建两个指针 pA 和 pB,分别初始化为链表 A 和 B 的头结点。然后让它们向后逐结点遍历。
// 当 pA到达链表的尾部时,将它重定位到链表 B 的头结点(你没看错,就是链表 B); 类似的,当 pB 到达链表的尾部时,将它重定位到链表 A 的头结点。
// 若在某一时刻 pA 和 pB 相遇,则 pA/ pB 为相交结点,此时pA路程为a+c+b, pB的路程为b+c+a
// 即使两个链表没有相交点,事实上,仍然可以统一处理,因为这种情况意味着相交点就是null
ListNode* GetIntersectionNode(ListNode *pHeadA, ListNode *pHeadB)
{
ListNode* pA = pHeadA;
ListNode* pB = pHeadB;
while (pA != pB)
{
pA = pA == nullptr ? pHeadB : pA->next;
pB = pB == nullptr ? pHeadA : pB->next;
}
// 打印
if (pA == nullptr)
{
printf("%s: no", __FUNCTION__);
}
else
{
printf("%s: %d", __FUNCTION__, pA->val);
}
return pA;
}
// 判断链表成环
// 快慢双指针实现
bool HasCycle(ListNode *pHead)
{
if (pHead == nullptr || pHead->next == nullptr)
return false;
ListNode *p1 = pHead;
ListNode *p2 = pHead->next;
while (p1 != p2)
{
if (p2 == nullptr || p2->next == nullptr)
{
return false;
}
p2 = p2->next->next;
p1 = p1->next;
}
return true;
}
}