【力扣每日一题】2023.7.31 重排链表

目录

题目:

示例:

分析:

代码:


题目:

【力扣每日一题】2023.7.31 重排链表_第1张图片

示例:

【力扣每日一题】2023.7.31 重排链表_第2张图片

分析:

给我们一个链表,让我们按照题目要求原地修改重排链表。

那么具体怎么个重排法呢,题目给出了一串式子,其实就是把链表分为前后两段,然后在前半段的节点中间穿插反过来的后半段链表,可以结合着我下面的动图理解理解。

【力扣每日一题】2023.7.31 重排链表_第3张图片

 我们现在就知道应该要怎么重排了,那么我们应该怎么做才能达到这样的效果呢?

我们可以发现一个规律,就是最前面的节点要指向最后面的节点,第二前的节点要指向第二后的节点,这个规律让我一下子就想到了双指针,然而直接对链表指向双指针的话,左指针可以右移,但是右指针不能左移,因为节点只有next(后驱指针),没有pre(前驱指针),所以我们得想个办法。

那就是用一个容器先按顺序把链表的每个节点都先缓存起来,再使用双指针的做法。

并且我们可以发现,按照这样的重排法,重排之后的链表末尾节点变成了重排之前链表的中间节点,因此我们可以先把中间节点的next改为空指针,也就是让中间的节点变为末尾节点。

一切准备就绪之后就可以使用双指针了,我们将左指针指向的节点的next指向右指针指向的节点,然后右指针指向的节点再指回左指针+1的指向的节点。然后再同时移动左右指针,直到左指针+1>=右指针,为什么要+1呢。

这就涉及到我们刚才的预处理了,我们提前把中间节点给设为链表末尾了,也就是它的next指向的是空指针,所以我们不需要处理,也不能处理它,要跳过它,所以要+1。

并且这个预处理是我们必须做的,我们可以先假设我们没有预处理中间节点,那么按照我们刚才的循环过程,最终会导致中间节点的next是自己本身,因此我们不得不提前将中间节点的指向改为空指针,并且在双指针循环的时候跳过这个节点。

 

代码:

class Solution {
public:
    void reorderList(ListNode* head) {
        vectorcache; //缓存住所有节点
        while(head){
            cache.push_back(head);
            head=head->next;
        }
        int l=0,r=cache.size()-1;
        //将链表的中间节点的next改为空指针,因为重排之后链表的最中间会变成链表的末尾
        if(cache.size()%2==0) cache[(l+r)/2+1]->next=nullptr;
        else cache[(l+r)/2]->next=nullptr;
        //修改左右指针所指节点的指向
        while(l+1next=cache[r];
            cache[r]->next=cache[l+1];
            l++,r--;
        }
    }
};

你可能感兴趣的:(力扣每日一题,leetcode,链表,算法,c++,数据结构)