链表遍历+取尾部+快慢指针 143. 重排链表

143. 重排链表

给定一个单链表 L:L0→L1→…→Ln-1→Ln ,
将其重新排列后变为: L0→Ln→L1→Ln-1→L2→Ln-2→…

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

示例 1:

给定链表 1->2->3->4, 重新排列为 1->4->2->3.

示例 2:

给定链表 1->2->3->4->5, 重新排列为 1->5->2->4->3.

解题1:每次取尾部,插入前面
挨个next遍历取尾部,费时;

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    void reorderList(ListNode* head) {
        if(!head) return;
        int n=0;
        ListNode * tmp=head;
        while(tmp){
            n++;
            tmp=tmp->next;
        }
        //总共n个节点
        ListNode* start=head;
        ListNode* tail=head;


        int t=0;
        while(t<(n+1)/2){
        for(int i=1;i<n;i++){
            tail=tail->next;   //第n个节点
        }
        Insert(start,tail);
        start=start->next;
        if(start) start=start->next;
        t++;
        tail=head;
        }
        if(start)
        start->next=nullptr;
    }
private:
    void Insert(ListNode *a,ListNode *b){  //把b插入a后面
        ListNode* t=a->next;
        a->next=b;
        b->next=t;
    }
};

解法2:将链表变成数组,每次取尾部插入前面
取尾部的时间节省不少;

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    void reorderList(ListNode* head) {
        if(!head) return;
        ListNode *tmp=head;
        while(tmp){
            res.push_back(tmp);
            tmp=tmp->next;
        }

        int start=0;
        int tail=res.size()-1;
        while(start<tail){
        res[start++]->next=res[tail];
        if(start<tail)
        res[tail--]->next=res[start];
        }
        res[start]->next=nullptr;
    }
private:
    vector<ListNode*> res;
};

解法三:快慢指针分断
(1)快慢指针将链表分段
(2)逆序后半部链表
(3)组合到head即可;

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    void reorderList(ListNode* head) {
        if(!head) return;
        ListNode* one=head;
        ListNode* two=head;
        while(one&&two&&two->next){
            one=one->next;
            two=two->next->next;
        }
        ListNode* r=one->next;
        one->next=nullptr;
        r=reverse(r);
        ListNode *tmp;
        while(head&&r){
            tmp=head->next;
            head->next=r;
            r=r->next;
            head->next->next=tmp;
            head=head->next->next;
        }

    }
private:        
    ListNode* reverse(ListNode* head){
        if(!head) return nullptr;
        ListNode dummyhead;
        ListNode*p=&dummyhead;
        p->next=head;
        ListNode *tmp;
        ListNode *f=head;
        ListNode *r=f->next;
        f->next=nullptr;

        while(r){ 
            if(r) {
            tmp=r->next;
            r->next=f; 
            p->next=r;
            }
            f=r;
            r=tmp;
        }
        return dummyhead.next;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值