LeetCode 143. Reorder List

97 阅读1分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第8天,点击查看活动详情

LeetCode 143. Reorder List

给定一个单链表 L **的头节点 head ,单链表 L 表示为:

L0 → L1 → … → Ln - 1 → Ln

请将其重新排列后变为:

L0 → Ln → L1 → Ln - 1 → L2 → Ln - 2 → …

不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。

 

示例 1:

输入: head = [1,2,3,4]
输出: [1,4,2,3]

示例 2:

输入: head = [1,2,3,4,5]
输出: [1,5,2,4,3]

 

提示:

  • 链表的长度范围为 [1, 5 * 104]
  • 1 <= node.val <= 1000

算法

(链表,模拟) O(n) 假设初始的链表是 L1→L2→L3→…→LnL1→L2→L3→…→Ln。

分两步处理:

1.将后半段的指针都反向,变成:L1→L2→L3→…→L⌈n/2⌉←L⌈n/2⌉+1←…←LnL1→L2→L3→…→L⌈n/2⌉←L⌈n/2⌉+1←…←Ln;
2.用两个指针分别从1和n开始往中间扫描,将后半段交替插入到前半段,变成:L1→Ln→L2→Ln−1→…;\

时间复杂度分析:整个链表总共扫描三次,第一次求总长度,第二次将后半段反向,第三次将后半段交替插入前半段,所以总时间复杂度是 O(n)。

先把链表的后半部分反转过来,然后就可以从两端开始遍历,将末尾节点插入第kk个节点后面。时间复杂度:查找中间节点O(n),反转后半部分链表O(n),依次插入后半部分的节点O(n),总的时间复杂度为O(n)。

C++ 代码

/**
 * 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) {
        int n = 0;
        for (ListNode *p = head; p; p = p->next) n ++ ;
        if (n <= 2) return;
        ListNode *later = head;
        for (int i = 0; i + 1 < (n + 1) / 2; i ++ )
            later = later->next;
        ListNode *a = later, *b = later->next;
        while (b){
            ListNode *c = b->next;
            b->next = a;
            a = b;
            b = c;
        }
        later->next = 0;
        while (head && head != a){
            b = a->next;
            a->next = head->next;
            head->next = a;
            head = head->next->next;
            a = b;
        }
    }
};

(暴力枚举) O(n2)

题解1:暴力解法,每次找到链表末尾节点插入到原来第kk个节点后面。时间复杂度O(n2)O(n2) C++ 代码

    void reorderList(ListNode* head) {
        if(!head || !head->next || !head->next->next)return ;
        ListNode* dummy = new ListNode(0);
        dummy->next = head;
        //head是第k个节点的位置
        while(head->next && head->next->next)
        {
            ListNode* tail = head;
            //找到末尾节点的前驱节点,同时将末尾节点插入到head后面
            while(tail->next->next) tail = tail->next;
            tail->next->next = head->next;
            head->next = tail->next;
            //更新tail和head
            tail->next = NULL;
            head = head->next->next;
        }
    }