#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;
}
}