文章目录
- 1、递归
- 2、leetcode509:斐波那契数列
- 3、leetcode206:反转链表
- 4、leetcode344:反转字符串
1、递归
函数自己调用自己
递归的4个点:
递归的例子:给一个数n,在斐波那契数列中,找到n对应的值
已知,f(0) = 0,f(1) = 1,求f(n)
一直拆f(n),直到拆到f(0)或者f(1)时终止,这就是函数能return的条件(终止条件),拆解条件则是
f(n) = f(n-1) + f(n-2)
接收的参数自然是n,根据递归这四个点,写递归函数:
2、leetcode509:斐波那契数列
public class P509 {public static int recursion(int n) {if (n < 2) {return n == 0 ? 0 : 1;}return recursion(n - 1) + recursion(n - 2);}
}
3、leetcode206:反转链表
之前引入了虚拟节点,遍历,修改next指针,来实现了反转。其实倒过来应该想到栈,先放进去,再倒出来,就反转了。
这里用递归,也是栈的味道:将节点的next值往下传,直到末尾节点,return,如上面示例中的,到5时终止递归,下一层到节点4,将5的指向改为4,此时4、5互指,为了防止环形链表的出现,将4到5的next指向给断掉。
1->2->3->4<->5
1->2->3->4<-5
返回节点4时,将5指向4,即node.next.next = node
public class P206Two {/*** 每次执行reverseList方法的参数:* 第一次递归:head = 1,拆解后向下传入的是head.next,为2* 第二次递归:head等于上一层传入的值,head = 2,向下传入的参数为3* 第三次递归:head等于上一层传入的值,head = 3,向下传入的参数为4* 第四次递归:head等于上一层传入的值,head = 4,向下传入的参数为5* 第五次递归:head等于5,return,这层的reverseList方法执行结束* 开始回溯:* 到第四次递归:继续往下执行方法,head = 4,head.next.next 即 5.next,执行head,即把5指向4* 到第三次递归:继续往下执行方法,head = 3,head.next.next 即 4.next,执行head,即把4指向3*/public static ListNode reverseList(ListNode head) {if (null == head || head.next == null) {return head;}ListNode newHead = reverseList(head.next);head.next.next = head;head.next = null;return newHead;}
}
4、leetcode344:反转字符串
这个题用双指针最好,指针L在开始,指针r在末尾,两个指针对向移动,一直互换元素,直到 L >= r。如下,h和o互换,左右指针移动,e和l互换……
这里以双指针的思想为基础,硬套一层递归来实现:还是L和r两个指针,递归终止的条件是 L >= r,递归的拆解则是每次L指针+1,r指针-1,递归要传递的参数不再是一个,而是L和 r 两个,上一层递归结束,回溯回来时,交换L和r位置的元素
public class P344 {/*** 双指针解法*/public static char[] reverseStringByTwoPoint(String s) {if (null == s || s.length() == 0){return null;}char[] charArray = s.toCharArray();int left = 0;int right = charArray.length - 1;while (left < right) {char temp;temp = charArray[left];charArray[left] = charArray[right];charArray[right] = temp;left++;right--;}return charArray;}/*** 双指针思想为基础,套一层栈的解法*/public static char[] reverseStringByRecursion(String s) {if (null == s || s.length() == 0){return null;}char[] charArray = s.toCharArray();int left = 0;int right = charArray.length - 1;return recursion(charArray, left, right);}public static char[] recursion(char[] charArray, int left, int right){// 递归终止的条件if (left >= right) {return charArray;}// 递归的拆解char[] array = recursion(charArray, left + 1, right - 1);// 上一层递归结束,回溯回来时,交换元素顺序char temp = array[left];array[left] = array[right];array[right] = temp;return array;}}
以hello为例,第一层递归,L = 0,R = 4,进入第二层递归,L = 1,R = 3,进入第三层递归,L= 2,R = 2,此时,触底,第三层递归函数执行return,结束,出栈。退到第二层递归,此时的L = 1, R = 3,交换这两个位置的元素,函数执行完成,出栈。退到第一层递归,此时L = 0,R = 4,交换这两个位置的元素,出栈。到此,三层递归都结束,方法执行结束。
递归时,盯清楚每一层递归时,参数等于多少,等递归回溯回来时,往下执行还要用。也别和传到下一层的参数混淆,因为用递归就会有参数拆解,每层递归函数里,值都不一样。如上,第一层递归,L = 0,R = 4,但其传入下一层递归的L和R分别为1和3