Bootstrap

反转链表 II-头插法

题目描述:

个人题解:

        整体思想是,在需要反转的区间里,每遍历到一个节点,让这个新节点来到反转部分的起始位置。下图展示了整个流程。

设置三个指针变量 precurrnext 来记录反转的过程中需要的变量,它们的意义如下:

curr:指向待反转区域的第一个节点 left;
next:永远指向 curr 的下一个节点,循环过程中,curr 变化以后 next 会变化;
pre:永远指向待反转区域的第一个节点 left 的前一个节点,在循环过程中不变。

代码实现:

struct ListNode *reverseBetween(struct ListNode *head, int left, int right) {
    // 因为头节点有可能发生变化,使用虚拟头节点可以避免复杂的分类讨论
    struct ListNode *dummyNode = malloc(sizeof(struct ListNode));
    dummyNode->val = -1;
    dummyNode->next = head;

    struct ListNode *pre = dummyNode;
    for (int i = 0; i < left - 1; i++) {
        pre = pre->next;
    }
    struct ListNode *cur = pre->next;
    struct ListNode *next;
    for (int i = 0; i < right - left; i++) {
        next = cur->next;
        cur->next = next->next;
        next->next = pre->next;
        pre->next = next;
    }
    return dummyNode->next;
}

复杂度分析:

时间复杂度:O(N),其中 N 是链表总节点数。最多只遍历了链表一次,就完成了反转。

空间复杂度:O(1)。只使用到常数个变量。

;