按照左右半区的方式重新组合单链表
题目描述:
给定一个链表list,
如果:
list = 1 调整之后1。
list = 1->2->3 调整之后1->2->3
list = 1->2->3->4 调整之后1->3->2->4
list = 1->2->3->4->5->6 调整之后1->4->2->5->3->6
list = 1->2->3->4->5->6->7 调整之后1->4->2->5->3->6->7
根据上面的规律,调整一个任意长度的链表。
题目难度:
medium
题目思路:
思路一:
对于链表相关的题目,第一想法应该是,把链表元素存入到数组中,然后再用一个新的help数组来记录,变化之后的每个位置的元素。最后把help数组中的元素一次串成新的链表。
思路二:
采用快慢指针的方式记录从哪个位置开始,之后的节点需要插入到之前的节点。然后再用链表指针变换的方式记录新组合的新的链表。
代码实现:
思路一:
public static Node changeList1(Node head) {
if (head == null || head.next == null || head.next.next == null) {
return head;
}
Node cur = head;
Node last = null; //用来记录奇数个时的最后一个节点
int size = 0;
while (cur != null) {
size++;
last = cur; //最后一个节点
cur = cur.next;
}
Node[] arr = new Node[(size & 1) == 0 ? size : size - 1]; //记录偶数个节点
cur = head;
for (int i = 0; i < arr.length; i++) {
arr[i] = cur; //链表的每个节点都存入到数组中
cur = cur.next;
}
Node[] help = new Node[arr.length]; //把数组中的每个节点按照题目变换位置
for (int i = 0; i < help.length; i++){
if (i < help.length/2){
help[2*i] = arr[i];
}else {
help[(i-help.length/2)*2+1] = arr[i];
}
}
int i =1;
while (i < help.length){
help[i-1].next = help[i]; //将数组中的元素转为链表
i++;
}
if ((size & 1)!= 0){
help[help.length - 1] .next = last;
}
return help[0]; //返回链表头结点
}
思路二:
public static Node changeList2(Node head){
if (head == null || head.next == null || head.next.next == null){
return head;
}
Node mid = head; //慢指针
Node right = head.next; //快指针
while (right.next != null && right.next.next != null){
mid = mid.next;
right = right.next.next;
}
right = mid.next; //需要重新插入的头结点
mid.next = null; //中间尾节点指向空
mergeRL(head,right); //合并前后两个节点
return head;
}
private static void mergeRL(Node left, Node right) {
Node next = null;
while (left.next != null){
next = right.next;
right.next = left.next;
left.next = right;
left = right.next;
right = next;
}
left.next = right;
}