206. Reverse Linked List

花式反转单链表

1. 用反转数组的思路:反转[1:] 然后把head 怼在后面。与数组不同“怼在后面” 这个操作是O(n) 效率很差。

    ListNode* reverseList(ListNode* head) {
        if (!head) return nullptr;
        if (!head->next) return head;
        ListNode* c = reverseList(head->next);
        ListNode* p = c;
        while (p->next) {
            p = p->next;
        }
        p->next = head;
        head->next = nullptr;
        return c;
    }

2. 改进上面的方法,优化掉后面那个O(n) 的添加操作。方法是:记住已反转好的tail,这样只用tail->next = head 就可以了,不需要遍历整个链表。

    ListNode* re(ListNode* head, ListNode** tail) {
        if (!head) return nullptr;
        if (!head->next) {
            *tail = head;
            return head;
        }
        
        ListNode* t{nullptr};
        ListNode* c = re(head->next, &t);
        t->next = head;
        head->next = nullptr;
        *tail = head;
        return c;
    }
    

    ListNode* reverseList(ListNode* head) {
        ListNode* t;
        return re(head, &t);
    }

3. 三指针。思路是从最普通的设想改进而来:

设想要反转 1->2->3->4->NULL

如果可以做到这样就好了:1<-2->3->4->NULL

比如现有指针p 指在2 上,现在只用把p 往前挪, 然后让p 指向2 就可以了。但是这个显然没法做到,因为这是一个单链表,不可能同时指向前和后。

那就想办法同时保存前后指针。

假设现在有两个链表:

1<-2<-r    h->3->4->NULL

r, h 分别指向两个链表的头部,则执行以下操作:

t = h;

h = h->next;

t->next = r;

r = t;

得到以下两个链表

1<-2<-3<-r   h->4->NULL

重复以上步骤,知道h 为NULL 时停止,则r 就指向反转后的链表。

    ListNode* reverseList(ListNode* head) {
        if (!head) return nullptr;
        ListNode* re = head;
        head = head->next;
        re->next = nullptr;
        while (head) {
            ListNode* t = head;
            head = head->next;
            t->next = re;
            re = t;
        }
        return re;
    }
原文地址:https://www.cnblogs.com/agentgamer/p/11352382.html