首页 > 代码库 > [C++]LeetCode: 75 Reorder List

[C++]LeetCode: 75 Reorder List

题目:

Given a singly linked list LL0L1→…→Ln-1Ln,
reorder it to: L0LnL1Ln-1L2Ln-2→…

You must do this in-place without altering the nodes‘ values.

For example,
Given {1,2,3,4}, reorder it to {1,4,2,3}.

思路:

我们可以先找到链表的中点(利用快慢指针),然后翻转链表的后半部分,再和前半部分链接到一起。

举例:如1-2-3-4-5-NULL, 我们翻转4-5-NULL,将前半部分链表3-NULL, 然后链接1-2-3-NULL, 5-4-NULL,依次将后半部分翻转链表插入,得到1-5-2-4-3-NULL.

Attention:

1. 注意把链表分为两部分时,前部分的尾节点要置为NULL

//(2)链接后一半的位置的节点作为链尾
        slow->next = NULL;
2. 翻转链表时,我们应构造一个虚拟头结点,因为要从头到尾翻转,所以每次都是插入到虚拟头结点之后,最初的head被不断后移。当然我们要首先判断后半部分链表是否符合翻转条件,或者是否存在节点。

if(head == NULL || head->next == NULL) return;
3. 注意我们通过快慢指针,得到中间节点时,后半部分链表的头结点应该是slow->next。

ListNode* reverseHead = slow->next;
4. 注意我们只在翻转链表存在节点时,将翻转链表中的节点插入到前半部分链表中。

 while(reverseHead != NULL)
5. 注意下插入的细节,我们是先保留后半部分链表头结点的下一个节点。再链接。

//翻转链表如果有节点 就继续链接
        while(reverseHead != NULL)
        {
            //保存后半截链表后一个节点
            ListNode* tmp = reverseHead->next;
            //连接两链表
            reverseHead->next = cur->next;
            cur->next = reverseHead;
            //确定两个链表的链接的新起点
            reverseHead = tmp;
            cur = cur->next->next;
        }      
复杂度:O(N)

AC Code:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    void reorderList(ListNode *head) {
        if(head == NULL || head->next == NULL) return;
        
        //(1) 找到链表的一半后一个结点
        ListNode* slow = head;
        ListNode* fast = head;
        while(fast != NULL && fast->next != NULL)
        {
            slow = slow->next;
            fast = fast->next->next;
        }
        
        ListNode* reverseHead = slow->next;
        //(2)链接后一半的位置的节点作为链尾
        slow->next = NULL;
        //(3) 翻转链表
        reverse_list(reverseHead);
        
        //(4) 链接两个链表
        ListNode* cur = head;
        //翻转链表如果有节点 就继续链接
        while(reverseHead != NULL)
        {
            //保存后半截链表后一个节点
            ListNode* tmp = reverseHead->next;
            //连接两链表
            reverseHead->next = cur->next;
            cur->next = reverseHead;
            //确定两个链表的链接的新起点
            reverseHead = tmp;
            cur = cur->next->next;
        }
        
        return;
    }

private:    
    //翻转链表
    void reverse_list(ListNode* &head)
    {
       if(head == NULL || head->next == NULL) return;
       ListNode dummyhead(0);
       dummyhead.next = head;
       ListNode* p = head;
       
       while(p->next != NULL)
       {
           ListNode* tmp = p->next;
           p->next = tmp->next;
           tmp->next = dummyhead.next;
           dummyhead.next = tmp;
       }
       
       head = dummyhead.next;
       return;
    }
};






[C++]LeetCode: 75 Reorder List