LeetCode143重排链表

本文探讨了两种链表重新排序的方法:一种是通过栈实现,将右半区压入并合并,另一种是原地反转后半区。作者详细解析了合并过程中的关键操作,并分享了每种方法的优缺点。

方法一找到中间后,右半区压入栈中,然后将两部分合并

class Solution {
public:
    void reorderList(ListNode* head) {
        ListNode* fast = head;
        ListNode* slow = head;
        ListNode* mid;
        stack<ListNode*> st;
        while (fast->next != NULL && fast->next->next != NULL) {
            slow = slow->next;
            fast = fast->next->next;
        }
        mid = slow;
        slow = slow->next;
        mid->next = NULL;
        while (slow != NULL) {
            st.push(slow);
            slow = slow->next;
        }
        while (head != NULL) {
            ListNode* nex = head->next;
            if (!st.empty()) {
                ListNode* ss = st.top();
                st.pop();
                ss->next = nex;
                head->next = ss;
                head = head->next;
                head = head->next;
            }
            else {
                head = head->next;
            }
        }
    }
};

值得注意的点就是两部分链表合并时出现的问题,采用弹出一个栈中的节点,就将他的前驱和后继都搞定,此时head的位置需要后移两个位置,才能到达新的节点。当栈中元素全部弹出,那么只需将head后移,就可以跳出循环。此处的解决方法,真的烦了我一整天。

方法二 将后半区原地反转,空间复杂度O(1)

class Solution {
public:
	void reorderList(ListNode* head) {
		ListNode* fast = head;
		ListNode* slow = head;
		while (fast->next != NULL && fast->next->next != NULL) {
			slow = slow->next;
			fast = fast->next->next;
		}
		ListNode* mid = slow;
		ListNode* cur = slow->next;
		mid->next = NULL;
		ListNode* next = NULL;
		ListNode* newhead = NULL;
		while (cur != NULL) {
			next = cur->next;
			cur->next = newhead;
			newhead = cur;
			cur = next;
		}
		while (head != NULL && newhead != NULL) {
			ListNode* temp1 = head->next;
			ListNode* temp2 = newhead->next;
			head->next = newhead;
			head = temp1;
			newhead->next = head;
			newhead = temp2;
		}
	}
};
### 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 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值