206 反转链表

206 反转链表_第1张图片

解题思路可以有两种方法:递归 or 迭代。

\qquad 迭代:通过使用for循环遍历,完成目标。方法直观,容易理解。
\qquad 递归:通过函数调用其自身,完成目标。递归最复杂、最重要的部分就是递归函数的构建,构建递归函数可以从以下几方面考虑:
\qquad\qquad 1)函数的终止条件的设立。
\qquad\qquad 2)目标拆解后,函数每一步需要重复执行的操作。
\qquad\qquad 3)不同递归层级间的信息传递,可借助参数、返回值、外部变量等。

递归思路:
\qquad 一开始的思路,从刚才上面三个角度分析:
\qquad 1)当前head为最后一个节点时,返回head,作为翻转后链表的表头。
\qquad 2)每一步重复将当前head添加到新链表的末尾。
\qquad 3)观察可发现,完成每一步的操作需要两个信息:
\qquad\qquad 1 - 翻转后链表的表头,用于题目输出,只能作为递归函数的返回值传递。
\qquad\qquad 2 - 翻转后链表的末尾,用于重复将当前节点添加到链表末尾,被函数各层调用使用,一开始的思路是,是用全局变量去存储链表末尾,并在每次操作后不断更新。

优化思路:
\qquad 思路大致相同,但是能否优化无需使用全局变量来存储链表末尾?
\qquad 可以利用链表本身的特性,找到链表的末尾,如下所示:
\qquad\qquad 1 → \rightarrow 2 → \rightarrow 3 → \rightarrow 4 → \rightarrow 5 \qquad (原本的链表)
\qquad\qquad 1 → \rightarrow 2 → \rightarrow 3 ← \leftarrow 4 ← \leftarrow 5 \qquad (部分反转的链表)
\qquad 现在,函数递归到节点2,如何找到翻转链表的末尾?从图中可以很直观的理解:
\qquad end node = 2 -> next, 只需要将 2 -> next -> next = node 2,便可以将2翻转:
\qquad\qquad 1 → \rightarrow 2 ← \leftarrow 3 ← \leftarrow 4 ← \leftarrow 5 \qquad

\qquad 另外需要注意的点,由于每次操作是重复的,如果仅仅改变指针的指向会导致反转后的链表未能指向nullptr,因此在每一步操作中,需额外将反转链表末尾指向nullptr

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        if(head == nullptr || head->next == nullptr)
        {
            return head;
        }
        ListNode* revhead = reverseList(head->next);
        head->next->next = head;
        head->next = nullptr;
        return revhead;
    }
}; 

你可能感兴趣的:(热题100,链表,链表,leetcode,c++)