1.题目
2.思路 --时间O(n) , 空间O(n)
仔细读题呀!!!!!!!!思路最重要,先不要着急写代码!!!
一开始想错了,以为是位置0 和 n- 1换位置, 1 和 n - 2 换位置.....
然后发现报错,一直都有环,才发现是题意理解错了(我想的问题更复杂,因为头和尾节点更复杂),题目明明写的是 0 和 1 之间插入倒数第一个节点n - 1,1 和 2 之间插入倒数第二个链表节点n - 2,以此类推.可以发现:
n = 0, 不需要交换节点
n = 1, 不需要交换节点
n = 2, 不需要交换节点
n = 3, 需要交换一个节点
n = 4, 需要交换一个节点
n = 5, 需要交换两个节点: 0,4 1,3,2
n = 6, 2;
n = 7, 3;
...
已经发现规律了,n >= 3,的等差数列.
那么问题来了,如何在两个节点中插入一个节点呢?--修改下一个指针即可,需要定义一个中间节点ListNode temp 来保存节点位置,跟swap两个值很像.
那么问题又来了,如何让每次插入的节点都是从末尾倒叙呢?链表是不支持顺序索引的.
我想的是用空间换时间,定义一个哈希表记录每一个节点的前驱节点,这样先移动tail指针到末尾,然后获取前驱节点,就可以倒叙遍历了.Map<ListNode, ListNode>
官方题解一用的是线性表来存储节点,也是可以的.List<ListNode>list = new ArrayList();
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public void reorderList(ListNode head) {
// if(head.next == null)return ;
ListNode tail = head;
ListNode head2 = head;
Map<ListNode, ListNode>map = new HashMap();
int n = 1;
while(tail.next != null){
map.put(tail.next, tail); // 位置i, 前一个节点
tail = tail.next;
n++;
}
if(n < 3)return ;
int temp = 3;
// System.out.println(n +">>" + map.get(head.next));
while(temp <= n ){
ListNode node = head2.next;
head2.next = tail;
tail.next = node;
// System.out.println(head2.val +">>"+ tail.val);
head2 = head2.next.next;
tail = map.get(tail);
tail.next = null;
temp += 2;
}
return ;
}
}
3.结果