1、通过快慢找到中点,分为前后两个链表,后一链表翻转,之后再合并,时间复杂度O(n)
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} head
无返回值:不要返回任何东西,而是修改head
* @return {void} Do not return anything, modify head in-place instead.
*/
var reorderList = function(head) {
let dummy=new ListNode(0);
dummy.next=head;
let slow=dummy;
let fast=dummy;
while(fast!=null){
slow=slow.next;
fast=fast.next;
if(fast!=null){
fast=fast.next;
}
}
let temp=slow.next;
slow.next=null
link(head,reverseList(temp),dummy);
};
var link=function(node1,node2,head){
let prev=head;
while(node1!=null&&node2!=null){
let tempNode=node1.next;
prev.next=node1;
node1.next=node2;
prev=node2;
node1=tempNode;
node2=node2.next;
}
// 若为奇数
if(node1!=null){
prev.next=node1;
}
}
// 翻转链表
var reverseList=function(list){
if(list==null){
return null
}
let prev=null;
let cur=list;
while(cur!=null){
let next=cur.next;
cur.next=prev;
prev=cur;
cur=next;
}
return prev
}
2、遍历遍历找到中点
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} head
无返回值:不要返回任何东西,而是修改head
* @return {void} Do not return anything, modify head in-place instead.
*/
var reorderList = function(head) {
let listLength=1;
for(let node=head;node!=null;node=node.next){
listLength++;
}
let node=head;
for(let i=0;i<listLength/2-1;i++){
node=node.next;
}
let lastHalf=node.next;
node.next=null;
link(head,reverseList(lastHalf))
};
var link=function(node1,node2){
// let dummy=new ListNode(0);
let prev=new ListNode(0);//用来指向头节点
// 一替一个接进去
while(node1!=null&&node2!=null){
prev.next=node1;
// 保存node1的下一个指针,为了一行将node1接上node2,且不丢失当前其后面的节点
let node1next=node1.next;
node1.next=node2;
prev=node2;
node1=node1next;
node2=node2.next;
}
// 对于一个链表中还没接完的情况,即奇数情况
if(node1!=null){
prev.next=node1;
}
}
// 翻转链表
var reverseList=function(list){
if(list==null){
return null
}
let prev=null;
let cur=list;
while(cur!=null){
let next=cur.next;
cur.next=prev;
prev=cur;
cur=next;
}
return prev
}
相比方法1,增加了遍历的时间,并且在主函数中没有使用dummy,只是在合并link函数中使用了dummy。(在主函数中实际不需要dummy)
注:为什么Link中写不写返回值,head都改变了?为什么在函数中改变了head,主函数中没变??
因为在主函数中head还是是链表第一个节点的(1),(1)只是指向变了
而且在其他函数中作为参数永远是传值调用,你只能修改head指向的内容,不能修改head本身。