重排链表

62 阅读1分钟

思路

先找出链表的中间节点,再把中间节点之后的链表反转,最后再把两个链表合并。总体的思路不难,但我在合并两个链表这一步卡了很久。

代码

/**
 * 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) {
        ListNode* mid=get_mid_node(head);
        ListNode* head2=reverse_node(mid);
        
        //由于反转链表之后,head最后一个元素会和head2最后一个元素相同
        //如果是while(head2),偶数时会出现问题,所以就干脆舍弃head2最后一个节点,反正这节点在head中有
        while(head2->next){
            //head:1->2->3
            //head2:5->4->3
            
            //先把各自的下一位保存起来
            ListNode* nxt=head->next,*nxt2=head2->next;
            //再把next指针分别指向对方
            head->next=head2;
            head2->next=nxt;
            //各自往后推
            head=nxt;
            head2=nxt2;
        }
        
        
    }
    //获取中间节点
    ListNode* get_mid_node(ListNode* node){
        ListNode* l1=node,*l2=node;
        while(l2&&l2->next){
            l2=l2->next->next;
            l1=l1->next;
        }
        return l1;
    }
    //反转链表
    ListNode* reverse_node(ListNode* node){
        ListNode* cur=node,*pre=nullptr;
        while(cur){
            ListNode* tem=cur->next;
            cur->next=pre;
            pre=cur;
            cur=tem;
        }
        return pre;
    }
};