版权声明:本文为博主原创文章,转载请注明出处:https://twocups.cn/index.php/2020/01/16/14/
最近我遇到了“反转链表”这道算法题,发现用递归解的人很少(LeetCode的官方答案中就有用递归解的,但那个答案不太好理解)。其实递归思想真的非常适合解决单向链表的题目,因为对单向链表使用递归时,相当于能反向遍历一遍链表,使单向链表具备双向链表的属性。这里是提供一种递归解法的思路,不是说递归解法是最好的。
题目描述
输入一个链表,反转链表后,输出新链表的表头。
链表结构
public class ListNode { int val; ListNode next = null; ListNode(int val) { this.val = val; } }
交换位置解法
public ListNode ReverseList(ListNode head) { if(head==null) return null; ListNode newHead = null; ListNode pNode = head; ListNode pPrev = null; while(pNode!=null){ ListNode pNext = pNode.next; if(pNext==null) newHead = pNode; pNode.next = pPrev; pPrev = pNode; pNode = pNext; } return newHead; }
递归解法
ListNode newln,p; public ListNode ReverseList(ListNode head) { this.tempReverseList(head,-1,false); return newln; } void tempReverseList(ListNode head,int val,boolean b){ if(head !=null){ this.tempReverseList(head.next,head.val,true); if(b == true){ p.next = new ListNode(val); p = p.next; } }else{ if(b == true) p = newln = new ListNode(val); } }
递归解法进阶版
public ListNode ReverseList(ListNode head) { if(head == null) return null; if(head.next == null) return head; ListNode node = reverseList(head.next); head.next.next = head; head.next = null; return node; }
“this.tempReverseList(head,-1,false);”
有点没看懂,这个-1和false是干什么用的?
设置“-1”和“false”的目的是相同的——为了让新生成的链表在正确的地方停止。
这个算法最核心的特点,就是利用递归来在当前链表结点获得前一个链表结点的值,这样就可以“逆序”遍历整个单向链表了。
那么问题来了,如果当前位置在原链表的表头会出现什么状况呢?
一个值为“-1”的链表结点将被生成,然后由于判断位“false”而不被加入新的链表,这样新链表就在正确的地方停止了。
其实,“-1”改成“-2”也可以,这只是占位置的,并且在我出错的时候可以明显地提醒我出错的地方。