链表反转/反转指定区间的链表/隔K隔反转链表

#include <iostream>
typedef struct node {
node* pNext;
int nVal;
node(int num) : pNext(nullptr), nVal(num) {}
};
node* create_link(int nCnt) {
if (nCnt <= 0) {
return nullptr;
}
node* pHead = new node(0);
node* pCur = pHead;
for (int i=1; i < nCnt; ++i) {
pCur->pNext = new node(i);
pCur = pCur->pNext;
}
return pHead;
}

void display_link(node* pHead) {
node* pCur = pHead;
while (pCur) {
std::cout << pCur->nVal << ",";
pCur = pCur->pNext;
}
std::cout << std::endl;
}

void clear_link(node* pHeader) {
int cnt = 0;
while (pHeader->pNext) {
node* pNext = pHeader->pNext;
delete pHeader;
++cnt;
pHeader = pNext;
}
if (pHeader) {
delete pHeader;
pHeader = nullptr;
++cnt;
}
}

// 原地反转链表
node* reverse(node* pHeader) {
if (nullptr == pHeader) {
return pHeader;
}
node* pCur = pHeader;
node* pLeft = nullptr;
node* pRight = nullptr;
while (pCur) {
pRight = pCur->pNext;
pCur->pNext = pLeft;
pLeft = pCur;
pCur = pRight;
}
return pLeft;
}

// 区间反转链表
node* reverse_M_N(node* pHeader, int M, int N) {
if (M*N <= 0) {
return pHeader;
}
if (M > N) {
return pHeader;
}
node* pCur = pHeader;
int curPos = 1;
if ( M == 1) {
node* pLeft = nullptr;
node* pRight = nullptr;
node* pTail = pCur;
while (pCur && curPos <= N) {
pRight = pCur->pNext;
pCur->pNext = pLeft;
pLeft = pCur;
pCur = pRight;
++curPos;
}
pHeader = pLeft;
if (pCur) {
pTail->pNext = pCur;
}
return pHeader;
} else {
// 走到 M-1 的位置处
int curPos = 1;
for (curPos=1; curPos < M -1 && pCur->pNext; ++curPos) {
pCur = pCur->pNext;
}
// M, N 将整个链表分为三个区间
// 区间1 的尾节点
node* p_part_1_tail = pCur;
pCur = pCur->pNext;
// 反转后区间2的尾节点
node* p_part_2_tail_after_reverse = pCur;
// 开始反转
node* pLeft = nullptr;
node* pRight = nullptr;
while (pCur && curPos < N) {
pRight = pCur->pNext;
pCur->pNext = pLeft;
pLeft = pCur;
pCur = pRight;
++curPos;
}
// 链接三部分区间
p_part_1_tail->pNext = pLeft;
p_part_2_tail_after_reverse->pNext = pCur;
return pHeader;
}
}

// 每 K个一组反转链表
node* reverse_m_group(node* pHeader, int k) {
if (nullptr == pHeader){
return nullptr;
}
// 分组
node* pCur = pHeader;
int totalCnt = 0;
while (pCur) {
++totalCnt;
pCur = pCur->pNext;
}
int grps = totalCnt / k;
// 重置 pCur
pCur = pHeader;
node* pLastPartTail = pCur;
node* pLeft = nullptr;
node* pRight = nullptr;
for (int i=1; i <= grps; ++i) {
int curCnt = 0;
node* pCurPartHeader = pCur;
while (pCur && curCnt < k) {
pRight = pCur->pNext;
pCur->pNext = pLeft;
pLeft = pCur;
pCur = pRight;
++curCnt;
}
if (1 == i) {
pHeader = pLeft;
} else {
pLastPartTail->pNext = pLeft;
pLastPartTail = pCurPartHeader;
}
}
// 追加剩余的节点
if (pCur) {
pLastPartTail->pNext = pCur;
}
return pHeader;
}

// 如何判断链表是否有环, 环入口
// 思路: 快慢指针, 快指针一次走2步, 慢指针一次走1步, 如果快慢指针有机会能相遇, 则证明有环
// 定理: 按照上述的步伐, 当两指针第一次相遇时, 快指针一定比慢指针多走了一圈的长度, 所以当相遇时, 慢指针继续, 快指针从头出发,
// 快慢指针均一次移动相同的步骤(1, 2, 3 ... N, N < 环入口的长度), 当两个指针相遇时, 即为环入口

// 如何判断两个链表是否相交, 求交点
// 快慢指针, 快指针一次两步, 慢指针一次一步,移动时各自记录自己的长度, 如果两个指针能相遇, 则相交

// 如何判断两个有环链表是否相交, 求环入口, 环长, 以及交点
// 1 判断是否相交 快慢指针即可, 相遇即相交
// 2 求环入口 => 单链表求环入口的思路求解
// 3 求环长 => 第一次相遇时, 快指针一定比慢指针多走了一圈的距离
// 4 求交点 => 用2 中思路求出入口, 然后用"如何判断两个链表是否相交, 求交点" 思路求出交点

int main() {
std::cout << "Hello, World!" << std::endl;
node* pHeader = create_link(10);
display_link(pHeader);
pHeader = reverse_M_N(pHeader, 3,8);
display_link(pHeader);
clear_link(pHeader);
return 0;
}

 

posted on 2020-08-22 21:17  我是某某某是我  阅读(282)  评论(0编辑  收藏  举报

导航