【算法】92. Reverse Linked List II

思路:

把指针移动到想要开始反转的节点,然后反转之后的K的节点。

代码:

递归反转整个链表:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        if (head == nullptr || head->next == nullptr) {
            return head;
        }

        ListNode* last = reverseList(head->next);
        head->next->next = head;
        head->next = nullptr;
        
        return last;
    }
};

这是链表的后序遍历。 

注意:要让本指针的next设为nullptr (head->next = nullptr),否则在第一个节点将会造成循环。返回last因为需要反转之后的链表的头节点。

递归反转链表的头N个值:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
ListNode* reverseN(ListNode* head, int n) {
    if (n == 1) {
        successor = head->next;
        return head;
    }

    ListNode* last = reverseN(head->next, n-1);
    head->next->next = head;
    head->next = successor;

    return last;
}

反转链表的一部分:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
private:
    ListNode* successor = nullptr;

public:
    ListNode* reverseBetween(ListNode* head, int left, int right) {
        if (head == nullptr || head->next == nullptr) {
            return head;
        }

        ListNode* dummy = new ListNode(-1);
        dummy->next = head;

        ListNode* p1 = dummy;
        for (int i = 0; i < left - 1; i++) {
            p1 = p1->next;
        }

        ListNode* last  = reverseN(p1->next, right-left+1);
        p1->next = last;
        return dummy->next;
    }

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

        ListNode* last = reverseN(head->next, n-1);
        head->next->next = head;
        head->next = successor;

        return last;
        
    }
};

需要dummy头节点是因为:reverseN(p1->next, right-left+1); 在这里p1是要翻转的前一个node,要用dummy防止从第一个node开始反转,此时前一个node是空的的情况。

记录:

一刷:5.27

没有用dummy节点

二刷:6.9

漏写了:

if (head == nullptr || head->next == nullptr) {
    return head;
}

right-left+1写成了left-right+1

链接:

https://leetcode.com/problems/reverse-linked-list-ii/

https://leetcode.com/problems/reverse-linked-list/

递归魔法:反转单链表 :: labuladong的算法小抄

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
链表反转是一道经典的算法问题,可以使用迭代或递归两种方法来实现。以下是使用迭代方法实现 C++ 链表反转的示例代码: ```cpp #include <iostream> using namespace std; struct ListNode { int val; ListNode *next; ListNode(int x) : val(x), next(NULL) {} }; class Solution { public: ListNode* reverseList(ListNode* head) { ListNode* prev = NULL; ListNode* curr = head; while (curr != NULL) { ListNode* nextTemp = curr->next; curr->next = prev; prev = curr; curr = nextTemp; } return prev; } }; int main() { ListNode* head = new ListNode(1); head->next = new ListNode(2); head->next->next = new ListNode(3); head->next->next->next = new ListNode(4); Solution solution; ListNode* newHead = solution.reverseList(head); while (newHead != NULL) { cout << newHead->val << " "; newHead = newHead->next; } return 0; } ``` 在这个示例代码中,我们定义了一个 `ListNode` 结构体来表示链表节点,它包含一个整数 `val` 和指向下一个节点的指针 `next`。然后我们使用迭代方法实现了 `reverseList` 函数,该函数接受一个链表头指针 `head`,并返回一个新的链表头指针,该链表是输入链表的反转。 在 `reverseList` 函数中,我们定义了两个指针 `prev` 和 `curr`,分别指向当前节点的前一个节点和当前节点。然后我们使用一个 `while` 循环遍历整个链表,每次将当前节点的 `next` 指针指向前一个节点 `prev`,然后将 `prev` 指针指向当前节点 `curr`,将 `curr` 指针指向下一个节点 `nextTemp`。最后返回 `prev` 指针,它指向了反转后的链表头节点。 在 `main` 函数中,我们创建了一个包含四个节点的链表,并将其传递给 `reverseList` 函数进行反转。最后我们遍历反转后的链表并输出结果。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值