力扣工作周刷题 - 143. 重排链表

2020.10.20
原题:点击此处

要求把链表从:
L1->L2->L3->…Ln的排序转变为
L1->Ln->L2->Ln-1->…

做这道题的时候真的立刻就想到了
1、快慢指针找链表中间点(因为改变链表序列之后,原来排序的中点必定是后来排序的结尾。)
题目
2、链表反转(因为可以看出改变链表序列后,Ln是倒放的)
题目
后面做了很多次草稿之后发现昨晚上面那两部之后,就不知道怎么办了。
查了题解发现是缺了链表合并这个步骤我没学过,通过这道题,学会了两个相同长度(或长度差为1)的链表如何进行合并。

空间复杂度O(1)
时间复杂度O(n)

Java版本

class Solution {
    public void reorderList(ListNode head) {
        if(head == null){
            return;
        }
        ListNode slow = head;
        ListNode fast = head;
        //找中间点
        while(fast != null && fast.next != null && fast.next.next !=null){
            slow = slow.next;
            fast = fast.next.next;
        }
        //反转
        ListNode pre = reverse(slow.next);
        //结尾置空,防止产生环
        slow.next = null;
        ListNode cur = head;
        //两个链表进行合并
        while(cur != null && pre !=null){
            ListNode L_temp = cur.next;
            ListNode R_temp = pre.next;
            cur.next = pre;
            cur = L_temp;
            pre.next = cur;
            pre = R_temp;
        }
    }
    
    public ListNode reverse(ListNode head){
        ListNode pre = null;
        ListNode cur = head;
        while(cur != null){
            ListNode temp = cur.next;
            cur.next = pre;
            pre = cur;
            cur = temp;
        }
        return pre;
    }
}

C++版本

class Solution {
public:
    void reorderList(ListNode* head) {
        if(head == nullptr){
            return;
        }
        ListNode* mid = searchMidNode(head);
        ListNode* l1 = head;
        ListNode* l2 = mid->next;
        mid->next = nullptr;
        l2 = reverseList(l2);
        mergeList(l1, l2);
    }

    ListNode* reverseList(ListNode* head){
        ListNode* pre = nullptr;
        ListNode* cur = head;
        while(cur != nullptr){
            ListNode* temp = cur->next;
            cur->next = pre;
            pre = cur;
            cur = temp;
        }
        return pre;
    }

    ListNode* searchMidNode(ListNode* head){
        ListNode* slow = head;
        ListNode* fast = head;
        while(fast != nullptr && fast->next != nullptr && fast->next->next != nullptr){
            slow = slow->next;
            fast = fast->next->next;
        }
        return slow;
    }

    void mergeList(ListNode* l1,ListNode* l2){
        ListNode* L_temp;
        ListNode* R_temp;
        while(l1!=nullptr && l2!=nullptr){
            L_temp = l1->next;
            R_temp = l2->next;
            l1->next = l2;
            l1 = L_temp;
            l2->next = l1;
            l2 = R_temp;
        }
    }

};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值