LeetCode 143. Reorder List(C++)

题目描述

Given a singly linked list L: L0→L1→…→Ln-1→Ln,
reorder it to: L0→Ln→L1→Ln-1→L2→Ln-2→…

You may not modify the values in the list’s nodes, only nodes itself may be changed.

Example 1:

Given 1->2->3->4, reorder it to 1->4->2->3.
Example 2:

Given 1->2->3->4->5, reorder it to 1->5->2->4->3.

算法

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

分三步处理:

  1. 将链表拆分为前后两段,要求偶数长度时前后半段长度相等,奇数长度时,前半段比后半段长一个结点。
  2. 将后半段的指针都反向,变成:L1→L2→L3→…→L⌈n/2⌉←L⌈n/2⌉+1←…←Ln;
  3. 用两个指针分别从1和n开始往中间扫描,将后半段交替插入到前半段,变成:L1n→L2→Ln−1→…;

时间复杂度分析:整个链表总共扫描三次,第一次求总长度,第二次将后半段反向,第三次将后半段交替插入前半段,所以总时间复杂度是 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) {
        if(!head) return ;
        if(!head->next) return;
        //拆分
        int n=0;//局部变量一定要初始化
        for(ListNode* p = head;p;p=p->next) n++;
        cout<<n<<endl;
        ListNode* mid = head;
        for(int i =0;i<(n+1)/2-1;i++) mid = mid->next; //条件
        ListNode *sec = mid->next;
        mid->next = 0;//前半串串尾置空
        //逆序
        ListNode* cur = sec->next;
        sec->next = 0;//后半串的头结点在逆序后变成尾结点,其next为空,之后sec作为cur的前驱
        while(cur)//退出条件为cur为空,此时cur的原前驱为后半串的头结点
        {
            ListNode* tmp = cur->next;
            cur->next = sec;
            sec = cur;
            cur = tmp;
            
        }
        
        //合并
        //奇数长度,前半段比后半段多以;偶数长度,前后一样长
        //直接用head遍历前半段,head是形参
        while(sec){
            //ListNdoe* next1 = head->next1;  此句多余
            ListNode* next2 = sec->next;
            sec->next = head->next;
            head->next = sec;
            sec=next2;
            head=head->next->next;
        }
        
        
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值