【LeetCode】reorder-list

题目描述

Given a singly linked list L : L0 ! L1 ! · · · ! Ln−1 ! Ln, reorder it to: L0 ! Ln ! L1 !
Ln−1 ! L2 ! Ln−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}.

首先,题目规定要in-place,也就是说只能使用O(1)的空间

解题思路
  • 观察新链表,它是在原链表的基础上一头一尾交替连接而成,所以原链表的前半段在新链表中是顺序的,后半段在新链表中是逆序的
  • 所以,我们的解题思路就是:通过快慢指针找到链表的中间节点,然后从中间节点处断开,将后半段链表进行逆置,然后将后半段链表节点插入到前半段链表中
  • 理清思路后,我们就可以开始写代码了,这个题的实现不但考察了我们接着道题的思路,同时也考察了链表逆置的算法
代码实现
  • void reorderList(ListNode *head)
void reorderList(ListNode *head)
{
    //如果链表为空,有一个节点,有两个节点,则不用进行处理
    if(head == NULL || head->next == NULL || head->next->next == NULL)
        return;
    //通过快慢指针寻找中间节点
    ListNode* fast = head;
    ListNode* slow = head;
    ListNode* prev = NULL;
    while(fast != NULL && fast->next != NULL)
    {
        prev = slow;
        slow = slow->next;
        fast = fast->next->next;
    }
    //将链表从slow(中间节点)处断开
    prev->next = NULL;
    //将链表的后半段进行逆置
    slow = reverse(slow);
    //将两条链表进行插入合并
    head = merge(head, slow);
}
  • 下面我们考虑链表逆置的实现,我们通过一张图来看一下链表逆置的过程,以帮助我们思路更清晰的写出代码,如下图所示:
    链表逆置
  • 代码实现如下:
ListNode* reverse(ListNode* head)
{
    if(head == NULL || head->next == NULL)
        return head;
    ListNode* cur = head;
    ListNode* prev = head;
    ListNode* next = cur->next;
    cur->next = NULL
    while(next != NULL)
    {
        prev = cur;
        cur = next;
        next = cur->next;
        cur->next = prev;
    }
    //最后一个节点单独处理
    cur->next = prev;
    prev = cur;
    return prev;
}
  • 最后是两条链表进行插入合并的实现:
//我们此处进行的是后半段链表在前半段链表的基础上插入合并
ListNode* merge(ListNode* head1, ListNode* head2)
{
    //两条链表都非空
    ListNode* cur = head1;
    ListNode* next = NULL;
    while(cur->next != NULL)
    {
        next = cur->next;
        cur->next = head2;
        head2 = head2->next;
        cur->next->next = next;
        cur = next;
    }
    cur->next = head2;
    return head1;
}
  • 代码的完整实现如下:
ListNode* reverse(ListNode* head)
{
    if (head == NULL || head->next == NULL)
        return head;
    ListNode* cur = head;
    ListNode* prev = head;
    ListNode* next = cur->next;
    cur->next = NULL;
    while (next != NULL)
    {
        prev = cur;
        cur = next;
        next = cur->next;
        cur->next = prev;
    }
    //最后一个节点单独处理
    cur->next = prev;
    prev = cur;
    return prev;
}

ListNode* merge(ListNode* head1, ListNode* head2)
{
    //两条链表都非空
    ListNode* cur = head1;
    ListNode* next = NULL;
    while (cur->next != NULL)
    {
        next = cur->next;
        cur->next = head2;
        head2 = head2->next;
        cur->next->next = next;
        cur = next;
    }
    cur->next = head2;
    return head1;
}
void reorderList(ListNode *head)
{
    //如果链表为空,有一个节点,有两个节点,则不用进行处理
    if (head == NULL || head->next == NULL || head->next->next == NULL)
        return;
    //通过快慢指针寻找中间节点
    ListNode* fast = head;
    ListNode* slow = head;
    ListNode* prev = NULL;
    while (fast != NULL && fast->next != NULL)
    {
        prev = slow;
        slow = slow->next;
        fast = fast->next->next;
    }
    //将链表从slow(中间节点)处断开
    prev->next = NULL;
    //将链表的后半段进行逆置
    slow = reverse(slow);
    //将两条链表进行插入合并
    head = merge(head, slow);
}

int main()
{
    ListNode* node1 = new ListNode(1);
    ListNode* node2 = new ListNode(2);
    ListNode* node3 = new ListNode(3);
    ListNode* node6 = new ListNode(6);
    ListNode* node7 = new ListNode(7);

    node1->next = node2;
    node2->next = node3;
    node3->next = node6;
    node6->next = node7;

    PrintList(node1);
    reorderList(node1);
    PrintList(node1);
    return 0;
}
  • 程序运行结果如下图所示:
    sort-list

猜你喜欢

转载自blog.csdn.net/Aurora_pole/article/details/81395721
今日推荐