Leetcode 92.反转链表II (中等)(递归反转单链表的一部分)

题目描述:

反转从位置 mn 的链表。请使用一趟扫描完成反转。

说明:
1 ≤ m ≤ n ≤ 链表长度。

示例:

输入: 1->2->3->4->5->NULL, m = 2, n = 4
输出: 1->4->3->2->5->NULL

思路:

首先我们考虑到的情况是,反转整个链表该怎样实现。

比较经典的解法是递归反转,代码简洁但需要仔细理解下:

struct ListNode {
    int val;
    struct ListNode *next;
};

//递归反转整个链表
struct ListNode* reverse(struct ListNode* head) {
    if (head->next == null) return head;
    struct ListNode* last = reverse(head->next);
    head->next->next = head;//将下一个节点变成当前节点的前驱节点
    head->next = null;
    return last;
}

下面是不用递归,而是用迭代法实现对链表的逆序。

 

typedef struct ListNode {
    int val;
    struct ListNode *next;
}ListNode;
ListNode reverseList(ListNode head)
{
    ListNode pre = NULL;
    while(head != NULL)
    {
        ListNode cur = head;
        head = head->next;
        cur->next = pre;
        pre = cur;
    }
    return pre;
}

接下来我们来考虑反转前N个节点又该如何解决:

//反转前N个节点
struct ListNode* successor = null; // 用来记录第n个节点的后驱节点

// 反转以 head 为起点的 n 个节点,返回新的头结点
struct ListNode* reverseN(struct ListNode* head, int n) {
    if (n == 1) { 
        // 记录第 n + 1 个节点
        successor = head->next;
        return head;
    }
    // 以 head->next 为起点,需要反转前 n - 1 个节点
    struct ListNode* last = reverseN(head->next, n - 1);

    head->next->next = head;
    // 将反转之后的 head 节点与后面的第n+1节点连起来
    head.next = successor;
    return last;
}    

此时,对于反转链表的一段我们则可以考虑将其分解为:

当其实点m为1时,即为反转前n个节点;

当m不等于1时,则递归的看作是反转head->next 的[m-1,n-1] 的节点;对于head->next->next 则是反转[m-2,n-2]的节点;递归下去。代码如下:

//反转一部分
struct ListNode* reverseBetween(struct ListNode* head, int m, int n) {
    // base case
    if (m == 1) {//相当于反转前n个元素
        return reverseN(head, n);
    }
    // 前进到反转的起点触发 base case
    head-.next = reverseBetween(head->next, m - 1, n - 1);
    return head;
}

题目的完整ac代码如下:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode* successor = NULL; //存放后驱节点

struct ListNode* reverseN(struct ListNode* head, int n){
    if(n==1){
        successor = head->next;
        return head;
    }
    struct ListNode* last = reverseN(head->next, n-1);

    head->next->next = head;//将下一个节点变成当前节点的前驱节点
    head->next = successor;
    return last;
}

struct ListNode* reverseBetween(struct ListNode* head, int m, int n){
    if(m == 1){
        return reverseN(head,n);
    }
    head->next = reverseBetween(head->next, m-1, n-1);
    return head;
}

 本文借鉴了labuladong 的题解。也推荐更多的朋友去学习借鉴labuladong 的文章。可关注他的公众号labuladong

 

 

 

 

 

 

你可能感兴趣的:(Leetcode,刷题笔记,链表操作)