Reverse Linked List II
发布日期:2021-05-15 08:35:33 浏览次数:18 分类:精选文章

本文共 1962 字,大约阅读时间需要 6 分钟。

链表反转是操作链表的一种常见问题,涉及复杂的指针操作和内部节点的调整。在此问题中,我们不仅需要将链表反转,还需要在原地完成操作(in-place),并且只能遍历链表一次。以下将详细介绍实现方法和步骤。

方法思路

  • 利用代理节点简化操作:在链表的开头添加一个临时节点(dummy node),其下方连接链表的第一个节点。这样在修改链表头部时,不需要特别处理。
  • 初始化前驱节点:将前驱节点设置为临时节点,便于在操作过程中持续追踪链表各节点的位置。
  • 迭代遍历指定节点:从参数中指定的节点开始,逐步调整前驱节点的指向和当前节点的指向,直到达到反转的目标节点。
  • 逆向构建新链表:将当前节点的下一个节点连接到目标链表的末尾,并将当前节点移动至目标链表的末尾,继续下一步操作。
  • 代码实现

    #include 
    struct ListNode {
    int val;
    ListNode* next;
    ListNode(int _val) { val = _val; }
    };
    class Solution {
    public:
    ListNode* reverse(ListNode* head, int m, int n) {
    ListNode dummy(-1);
    dummy.next = head;
    ListNode* prev = &dummy;
    // 迭代m-1次至目标节点
    for (int i = 0; i < m - 1; ++i) {
    prev = prev->next;
    }
    ListNode* target = prev->next;
    prev->next = NULL;
    // 从目标节点开始逆向构建链表
    for (int i = m; i < n; ++i) {
    ListNode* next_node = target->next;
    target->next = prev;
    prev->next = next_node;
    prev = target;
    target = next_node;
    }
    return dummy.next;
    }
    void show(ListNode* ln) {
    for (; ln != NULL; ln = ln->next) {
    printf("%d\n", ln->val);
    }
    }
    int main() {
    ListNode l1(1), l2(2), l3(3), l4(4);
    l1.next = &l2;
    l2.next = &l3;
    l3.next = &l4;
    l4.next = NULL;
    Solution so;
    ListNode* ad = so.reverse(&l1, 1, 4);
    so.show(ad);
    return 0;
    }
    };

    解释步骤

  • 初始化临时节点:创建一个dummy节点,用于简化链表操作,避免处理链表头部时的特殊情况。
  • 前驱节点初始化:将prev设置为dummy节点。
  • 迭代至目标节点:通过循环迭代,移动到要开始反转的节点位置m
  • 构建新链表:从目标节点开始,将后续节点逐个连接到目标链表的末尾,直到完成完整的反转操作。
  • 显示结果:调用show函数输出反转后的链表内容。
  • 示例结果

    输入链表:1 -> 2 -> 3 -> 4 -> 5 -> NULL

    反转范围:m=2, n=4
    输出链表:1 -> 4 -> 3 -> 2 -> 5 -> NULL

    该方法通过一次遍历完成链表反转,且空间复杂度为O(1),是空间高效的解决方案。

    上一篇:测试libevent的使用
    下一篇:双链表相加问题

    发表评论

    最新留言

    关注你微信了!
    [***.104.42.241]2025年04月22日 19时06分49秒