
1.理解题意
反转链表的目标是清晰明确的,就是将一个链表(1->2->3->4->5)反转成(5->4->3->2->1)。对于反转问题,我们并不陌生,数组有反转,字符串有反转,一切皆可反转呗!但单链表的反转却有点不一样,我们只能单方向遍历链表,那么常用的左右指针就用不到了哦!只能根据链表自身的特点来思考其他的方法。
2.思路分析
有两种思路,一种是使用递归,自底向上求解;另一种是使用迭代,自顶向下求解。
2.1 递归
说到递归,那这个问题一定有一个与之对应的递推结构,换句话说就是这个问题可以由与其相同的较小规模的问题而得到(就像报数一样,最后一个人不知道自己是第几个,只能从倒数第二个人的序号中得出,倒数第二个人同样不知道自己是第几个,只能从倒数第三个人的序号中得出,…, 直到问到第一个人,他前面没有人了,知道自己的序号是1号,接着第二个人也知道了,…, 最终传到最后一个人,我们得到了一个队伍的人数)
同样的,来想一想反转链表,我们要反转4个结点的链表,一下子好像做不到,那我们就先反转后三个结点,哎?一下子也做不到,那就反转后两个结点,哦可以哎!但是不要着急(就像第二个报数的人虽然知道自己前面就一个人,但他也不能把第一人给无视了啊),最后反转一个结点,最后一个结点后面没有结点了(指向null),不需要反转,直接返回就行。那再反过来想,最后一个不用反转,那就反转最后两个结点,现在就变成了(1->2->3<-4)那后三个结点不就变成反转两个结点的操作了吗?(把后两个结点看作一个整体),那太完美了,这样的话,我每次就相当于只反转两个结点,直到4个结点的时候,我就把整个链表反转了。
总结一下上面这个过程,反转n个结点的链表,可以由第一个结点和已经反转好的n-1个结点的链表做反转两个结点的操作而得到。

理解思路之后就来写代码吧!
public ListNode reverseList(ListNode head) {if(head == null) return null;//base caseif(head.next == null) return head;//Last用来保存反转后的头结点ListNode Last = reverseList(head.next);//反转两个结点的操作,就是将后一个结点指向当前结点head.next.next = head;//反转的链表指向的rest(剩余结点只有null)head.next = null;return Last;}
关于上面为什么head.next指向的是null,这个在反转链表的前n个结点里面,我们能更好的理解。
2.2 迭代
迭代的方法就比较直接明了了,就是自顶向下,一个一个往下转变指针的方向就行了,当然其中需要几个变量来辅助我们操作链表。

上面就是基本的步骤,很清晰了,不再赘述。
public ListNode reverseList(ListNode head) {
if(head == null) return null;
ListNode prev, cur, nxt;
prev = null; cur = nxt= head;
while(cur != null){
nxt = cur.next;
cur.next = prev;
prev = cur;
cur = nxt;
}
return prev;
}
