方法一(最优) : 通过两个变量实现链表的反转,
技巧为:取值,反转,右移,拿值
取值是怕在反转的时候把 next 节点给弄丢了,所以先保存下一个节点的值
反转是核心步骤,即 (要反转的节点)head.next = pre(反转的方向);
右移是为了进行下一次的反转
拿值也算是右移,因为有两个变量,所以要两次右移
public ListNode ReverseList(ListNode head) {
if(head == null) return null;
ListNode cur = null;
ListNode pre = null;
while(head != null){
cur = head.next;//取值
head.next = pre;//反转
pre = head;//右移
head = cur;//拿值
}
//这时候head 跑到最后已经为null了,pre才是返回的
return pre;
}
方法二(巧妙的递归反转)
巧就巧在 : head.next.next = head; 意思是,我的下一个的节点的下一个节点就是我, 假设 a -> b -> c,那从 b 开始,b.next 就是 c, 那我把c.next 赋为 b, 不就是巧妙的变成 a -> b <- c 了吗,但是还有一个步骤就是,必须把 b.nexy = null; 因为反转最后一个元素时,需要把null 赋给它的 next, 而 非尾节点会在下一次的反转中得到它的 next 节点,也就是箭头。
public ListNode ReverseList(ListNode head) {
if(head == null || head.next == null) return head;//先定义退出条件,递归必须点
ListNode cur = ReverseList(head.next);//递归操作,并保存每次操作的节点
//倒数第二个节点在这里先执行
head.next.next = head;//巧妙之处, 可以看做 (下一个节点) a = head.next a.next = head(前一个节点)
head.next = null;//必须点,得把他指向的箭头拆掉,等上一个继续反转,再付给他箭头
return cur;
}
双链表的反转,需要两次反转,其他思路跟单链表一样
取值,反转,反转,右移,右移
public DoubleNode DoublereverseList(DoubleNode head){
DoubleNode pre = null;
DoubleNode next = null;
while (head != null){
next = head.next;//取值
head.next = pre;//反转
head.last = next;//反转,两次
pre = head;//右移
head = next;//右移
}
return pre;
}