LeetCode143 重排链表(双指针)

本文介绍了一种解决LeetCode 143题目的高效算法。通过快慢指针找到链表中点,将后半部分链表逆置后与前半部分交替合并。该算法的时间复杂度为O(n),空间复杂度为O(1)。

题目链接:leetcode143

题面

在这里插入图片描述

题目大意

解题思路

首先用快慢指针找到链表的中点,并分成两个链表,为了方便操作,前面的链表的长度要大于等于后面的链表;

接着,把后面的链表逆置,为了方便操作,前面链表的链尾可以暂时称位后面链表的头节点;

最后将两个链表归并,由于归并操作要交替插入,于是我们结束的标志是后面链表完全插入到前面的链表的时候算法结束,这也是为什么我们要使得前面的链表元素不小于后面链表的原因。

时间复杂度 O ( n ) O(n) O(n),空间复杂度 O ( 1 ) O(1) O(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) {
        if (head == NULL) return ;
        ListNode *q, *p, *newHead;
        
        //找到中点 分为两条链表
        q = p = head;
        while (q && q->next) {
            p = p->next;
            q = q->next->next;
        }
        newHead = p; //前面的链表的尾指针充当后面链表的头节点
        
        //逆置后面的链表
        q = newHead->next; 
        newHead->next= NULL;
        while (q) {
            p = q->next;
            q->next = newHead->next;
            newHead->next = q;
            q = p;
        }
        
        //合并两个链表
        q = newHead; 
        newHead = newHead->next;
        q->next = NULL;
        
        q = head->next; p = newHead; newHead = head;
        while (p) {
            newHead->next = p;
            newHead = p;
            p = q;
            q = newHead->next;
        }
        
        return ;
    }
};
### LeetCode 重排链表 解题思路和方法 #### 方法1——线性表辅助 ##### 思路分析 为了简化操作,可以先遍历整个链表并将所有节点存储在一个列表中。之后按照新顺序重新连接这些节点即可。这种方法虽然额外使用了O(n)的空间来保存节点指针,但是逻辑简单易懂。 对于给定的单链表 L:L0→L1→…→Ln-1→Ln ,将其重新排列后变为:L0→Ln→L1→Ln-1→L2→Ln-2→… 此过程可以通过创建一个数组来暂存所有的节点,再通过双指针的方式从前向后以及从后向前交替取出节点并构建新的链接关系[^1]。 ```python def reorderList(self, head: ListNode) -> None: if not head or not head.next: return nodes = [] current = head while current: nodes.append(current) current = current.next left, right = 0, len(nodes) - 1 last = head while left < right: nodes[right].next = nodes[left].next nodes[left].next = nodes[right] last = nodes[left] left += 1 right -= 1 last.next = None ``` #### 方法2——中间节点+反转链表+合并链表 ##### 思路分析 该方案旨在优化空间复杂度至 O(1),即不借助额外的数据结构完成任务。具体步骤如下: 1. 找到原链表的中间位置; 2. 对从中点开始直到结尾的部分执行逆序处理; 3. 将前半部分与经过翻转后的后半部分依次交错相连形成最终的结果链表[^2]。 找到链表中心的方法是利用快慢两个指针同时出发,当快速指针到达终点时,慢速指针正好位于中部;而针对长度为奇数的情况,则让较短的一侧多保留一个元素作为起始点[^4]。 ```python def reorderList(self, head: ListNode) -> None: if not head or not head.next: return # 寻找链表中点 slow, fast = head, head while fast and fast.next: slow = slow.next fast = fast.next.next # 反转后半部分链表 prev, curr = None, slow.next while curr: next_temp = curr.next curr.next = prev prev = curr curr = next_temp slow.next = None # 合并两部分链表 first_half, second_half = head, prev while second_half: temp1, temp2 = first_half.next, second_half.next first_half.next = second_half second_half.next = temp1 first_half, second_half = temp1, temp2 ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小胡同的诗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值