今天学习的内容是对于链表的反转,主要有两种思路:使用虚拟节点辅助进行链表反转以及直接进行反转。
使用虚拟节点的思路比较简单,即把虚拟节点当作头结点,位置不变,然后遍历链表,把每一个节点的接入到虚拟节点的下一位即可,这里需要注意的是,插入的第一个节点在遍历结束后,它在新链表的末尾位置,其next应为null,所以我们可以在创建虚拟节点的定义其next为null即可:
public ListNode reverseList(ListNode head) {
ListNode res = new ListNode(0);//虚拟节点
res.next = null;
ListNode cur = head;
while (cur != null) {
ListNode next = cur.next;
cur.next = res.next;
res.next = cur;
cur = next;
}
return res.next;
}
第二种方法是不借助虚拟节点,直接对链表进行操作,这也是面试时常考察的一种思路,我的感觉是可以自己先画图理解,中间最重要的就是每一个操作的顺序十分的关键,中间改变一个操作顺序结果都会完全不同,还有一个要注意的点就是末尾注意不要形成环了:
public ListNode reverseList(ListNode head) {
ListNode pre=null;
ListNode cur=head;
while (cur!=null){
ListNode next=cur.next;
cur.next=pre;
pre=cur;
cur=next;
}
return pre;
}
拓展一下,还有一种方法就是利用递归,我感觉大多数的这种递归思路,不要深入地去理解,这样只会越想越复杂,容易让自己绕进去,对于这种递归从简单的入手,从最外层入手比较好观察:
public ListNode reverseList(ListNode head) {
if(head==null||head.next==null){
return head;
}
ListNode newNode=reverseList(head.next);
head.next.next=head;
head.next=null;
return newNode;
}