递归法
在遍历链表时,使用的都是相同操作来操作链表的不同部分,此时可以采用递归法。
在双指针法(🔗)中的反转链表,两两交换链表中的节点都可以使用递归法,以两题为例:
反转链表
递归方法一:
递归法相对抽象一些,但是其实和双指针法是一样的逻辑,同样是当cur为空的时候循环结束,不断将cur指向pre的过程。
关键是初始化的地方,可能有的同学会不理解, 可以看到双指针法中初始化 cur = head,pre = NULL,在递归法中可以从如下代码看出初始化的逻辑也是一样的,只不过写法变了。
class Solution {/*** 递归法(从前向后)** @param head* @return*/public ListNode reverseList(ListNode head) {return reverse(null, head);}private ListNode reverse(ListNode pre, ListNode cur) {// 当cur为空时停止递归if (cur == null) {return pre;}// 保存下一个节点ListNode tmp = cur.next;// 转换指针指向cur.next = pre;// 继续调用递归return reverse(cur, tmp);}}
递归方法二:
// 从后向前递归class Solution {ListNode reverseList(ListNode head) {// 边缘条件判断if(head == null) return null;if (head.next == null) return head;// 递归调用,翻转第二个节点开始往后的链表ListNode last = reverseList(head.next);// 翻转头节点与第二个节点的指向head.next.next = head;// 此时的 head 节点为尾节点,next 需要指向 NULLhead.next = null;return last;}}
两两交换链表中的节点
递归法
class Solution {/*** 递归法(从右到左)** @param head* @return*/public ListNode swapPairs(ListNode head) {// 递归结束的条件if (head == null || head.next == null) {return head;}// 获取头结点的下一个节点ListNode nextNode = head.next;// 调用递归进行循环ListNode newNode = swapPairs(nextNode.next);// 转换指针指向nextNode.next = head;head.next = newNode;// 返回nextNode用来连接上一个节点return nextNode;}}
92. 反转链表 II
递归法
https://labuladong.github.io/algo/2/18/18/
public ListNode reverseBetween(ListNode head, int left, int right) {if (left == 1) {return reverseN(head, right);}head.next = reverseBetween(head.next, left - 1, right - 1);return head;}ListNode successor = null;public ListNode reverseN(ListNode node, int n) {if (n == 1) {// 停止递归,并记录下一个节点successor = node.next;// 反转本身return node;}ListNode last = reverseN(node.next, n - 1);node.next.next = node;node.next = successor;return last;}
迭代法
https://leetcode.cn/problems/reverse-linked-list-ii/solution/fan-zhuan-lian-biao-ii-by-leetcode-solut-teyq/
迭代法思路不难,就是找到中间的链表,置null后,单独反转后在连接。
public ListNode reverseBetween(ListNode head, int left, int right) {ListNode dummy = new ListNode(-1);dummy.next = head;ListNode pre = dummy;// 找到开始交换链表的前一个节点for (int i = 0; i < left - 1; i++) {pre = pre.next;}ListNode rightNode = pre;for (int i = 0; i < right - left + 1; i++) {rightNode = rightNode.next;}ListNode succ = rightNode.next;ListNode leftNode = pre.next;// 注意置为null,再反转rightNode.next = null;pre.next = null;// 第 4 步:同第 206 题,反转链表的子区间reverse(leftNode);pre.next = rightNode;leftNode.next = succ;return dummy.next;}public void reverse(ListNode head) {ListNode cur = head, pre = null;while (cur != null) {ListNode temp = cur.next;cur.next = pre;pre = cur;cur = temp;}}
