第一种解法:建立虚拟头结点
public NodeList reversList(NodeList head){
NodeList ans =new NodeList(-1);
NodeList cur = head;
while (cur!=null){
//首先保存next不然后面就找不到了
NodeList next = cur.next;
//第一步,先把head接到ans的后面,相当于在ans和ans.next中间插入一个head,
//所以cur才指向ans的next
cur.next=ans.next;
//然后再ans指向cur就可以辣
ans.next=cur;
//重定向cur
cur=next;
}
return ans.next;
}
想象一下,刚开始的时候虚拟头结点和虚拟头结点的next节点是两个节点,我们需要做的是把目标节点一个一个放在虚拟头结点的后面,首先目标节点要先指向ans.next,然后ans指向cur目标节点,这样下来,目标节点就成功插入进去了,进而取代它原本的ans.next成为了新的ans.next节点,而目标链表损失一个节点,它的一个节点就成为下次循环的目标节点,我们也只关注ans和ans.next和目标节点cur就可以了
第二种解法:直接操作链表
public NodeList reversList(NodeList head){
NodeList pre =null;
NodeList cur = head;
while (cur!=null){
//本来是head的cur的现在变成末尾,末尾呢指向pre,刚开始为null,cur和pre都要向后移,
// 下一个cur必然要指向上一个cur,pre就是指向上一个cur的节点
NodeList next = cur.next;
cur.next = pre;
pre=cur;
cur=next;
}
return pre;
}
这里要虚拟出一个pre节点,目标节点要从头开始一个个断开,第一个断开指向pre,然后pre向前移动,现在的pre就是第一个断开的节点,请记住,pre节点就是用来被断开的节点指向的,断开之后就会被下一个节点指向,所以就从指向别人变成了被指向,就实现了反转了。
第三种解法:递归
public NodeList reversList2(NodeList head){
if (head==null||head.next==null){
return head;
}
NodeList newHead = reversList2(head.next);
head.next.next = head;
head.next=null;
return newHead;
}
这个我认为理解的难点在于
head.next.next = head;
这句话的目的是反转head的指向,由指向别人变成被别人指向,假设原始链表是1 -> 2 -> 3 -> 4 -> 5那么递归结束的条件是head=5,head=5就是上一步的结果newHead,上一步的head就是4,假设head的next节点是nextHead节点,那么正常的逻辑应该是head.next=nextHead;要实现反转就是要next要指向head,就是next的下一个节点是head,nextHead.next =head,也就是head.next.next=head成立。