天梯赛 L3 重排链表

题目链接:点击打开链接

思路:先根据题目信息找到原始链表,然后根据规则重排

#include <bits/stdc++.h>
using namespace std;
int head;
int data[100010],nex[100010];
int main(){
	int n;
	cin >> head >> n;
	for(int i = 0;i < n;i++){
		int h,d,ne;
		cin >> h >> d >> ne;
		data[h] = d;
		nex[h] = ne;
	}
	vector<int> v,re;
	int now = head;
	while(now != -1){
		v.push_back(now);
		now = nex[now];
	}
	int i = 0,j = v.size() - 1;
	while(i <= j){
		re.push_back(v[j--]);
		if(i > j) continue;
		re.push_back(v[i++]);
	}
	for(int i = 0;i < re.size() - 1;i++){
		printf("%05d %d %05d\n",re[i],data[re[i]],re[i + 1]);
	}
	int in = re.size() - 1;
	printf("%05d %d %d\n",re[in],data[re[in]],-1);
	return 0;
}

### 天梯赛重排链表算法实现与解思路 对于天梯赛中的 **重排链表** 问,其核心在于如何通过操作单向链表的节点顺序,使其满足特定的要求。以下是详细的分析和解决方案。 #### 目解析 目要求将一个单向链表 \( L_1 \to L_2 \to \ldots \to L_{n-1} \to L_n \) 转换为新的形式 \( L_1 \to L_n \to L_2 \to L_{n-1} \to L_3 \to L_{n-2} \ldots \)[^2]。这种转换可以通过双指针技术或者辅助数据结构(如栈或数组)完成。 --- #### 方法一:基于双端队列的方法 此方法的核心思想是利用双端队列存储原链表的所有节点值,随后按照交替弹出的方式重建新链表。 ##### 步骤说明 1. 使用 `deque` 数据结构保存原始链表的所有节点值。 2. 初始化一个新的头结点用于构建目标链表3. 循环从双端队列两端依次取出元素并连接到新链表中,直到队列为空为止。 ##### Python 实现代码 ```python from collections import deque class ListNode: def __init__(self, val=0, next=None): self.val = val self.next = next def reorderList(head): if not head or not head.next: return head node_values = [] current = head while current: # 将链表转存至列表 node_values.append(current.val) current = current.next reordered_list = deque(node_values) dummy = ListNode(-1) # 哑节点作为起始位置 tail = dummy flag = True # 控制取头部还是尾部 while reordered_list: if flag: value = reordered_list.popleft() else: value = reordered_list.pop() new_node = ListNode(value) tail.next = new_node tail = new_node flag = not flag # 切换标志位 return dummy.next ``` 这种方法的时间复杂度为 \( O(n) \),空间复杂度也为 \( O(n) \),因为额外使用了一个双端队列来暂存节点值。 --- #### 方法二:基于反转链表的技术 另一种更高效的解决方式是通过对链表进行分割、反转以及合并三个阶段的操作来达到目的。 ##### 步骤说明 1. 找到链表中间节点并将链表分成两部分; 2. 对第二部分链表执行反转操作; 3. 合并两个子链表形成最终的目标链表。 ##### Python 实现代码 ```python class Solution: def reorderList(self, head): if not head or not head.next: return head # Step 1: Find the middle of the list using slow and fast pointers. slow, fast = head, head while fast and fast.next: slow = slow.next fast = fast.next.next # Step 2: Reverse the second half of the linked list. prev, curr = None, slow while curr: temp = curr.next curr.next = prev prev = curr curr = temp first_half, second_half = head, prev # Step 3: Merge two halves alternately. while second_half.next: tmp_first = first_half.next tmp_second = second_half.next first_half.next = second_half second_half.next = tmp_first first_half = tmp_first second_half = tmp_second ``` 该方法仅需常数级的空间开销,时间复杂度仍保持在 \( O(n) \)[^1]。 --- #### 总结对比 | 方案 | 时间复杂度 | 空间复杂度 | 特点 | |--------------|------------|------------|----------------------------------------------------------------------| | 双端队列法 | \(O(n)\) | \(O(n)\) | 易于理解,适合初学者;但占用较多内存 | | 分割反转法 | \(O(n)\) | \(O(1)\) | 更加高效,无需额外存储空间;逻辑稍显复杂 | 两种方案各有优劣,在实际应用中可根据具体需求选择合适的一种。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值