• 链表反转/反转指定区间的链表/隔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;
    }
    除特殊说明外,其余所有文章均属原创。未经允许,请勿进行转载或者其他操作 有问题欢迎留言交流
  • 相关阅读:
    phpstorm实现分屏展示代码
    Yii2 JWT
    JSON Web Token 入门教程
    Linux常用命令: zip、unzip 压缩和解压缩命令
    yii2表单提交CSRF验证
    解决jquery click事件执行两次
    《Inside C#》笔记(十二) 委托与事件
    MVC与单元测试实践之健身网站(七)-日程与打卡
    《Inside C#》笔记(十一) 运算符重载
    MVC与单元测试实践之健身网站(七)-添加计划
  • 原文地址:https://www.cnblogs.com/LiuBingBlogs/p/13547138.html
Copyright © 2020-2023  润新知