递归
方法调用自己本身,叫递归
三个要素
- 边界条件
- 递归前进段
- 递归返回段
例1:在有序序列(比如有序数组)中,将查找的值跟数组的中间元素的值比较,如果查找值大于数组中间的元素,则继续到后半部分的范围查找,如果查找值小于数组中间的元素,则继续到前半部分的范围查找,如果等于,则返回该元素。以此类推。
public static int binSearch(int[] a,int key,int left,int right) {
int mid = (left+right)/2;//取中点
if(left>right) {//没查找到,退出
return -1;
}
if(a[mid]==key) {//找到了,返回下标索引
return mid;
}else if(key<a[mid]){
return binSearch(a, key, left, mid-1);//中间值大于要查找的值,递归查找左半边
}else {
return binSearch(a, key, mid+1, right);//中间值小于要查找的值,递归查找右半边
}
}
例二:
无论多少个盘子,都看成只有两个盘子,比如,有N个盘子在塔座A上,我们假设其为两个盘子,其中的1到(N-1)个
盘子看成一个小盘子,最下面的第N个盘子看成一个大盘子,解决步骤:
(1)先将N-1个盘子从初始塔座A移动到中介塔座B上。
(2)此时将初始塔座A上级仅剩的最大的一个盘子移动到目标塔座C上。
(3)塔座B上还剩下N-1个盘子,塔座A为空,塔座C仍然为目标塔座,现在变成了n-1个盘子放到初始塔座B,中介塔
座A,目标塔座C的汉诺塔问题了。
经典中的经典
package cn.datastruct.recursion;
public class HuoNuoTa {
/**
* 先分析最简单的问题,将一个盘子从a移到c直接拿过去就可以了
* 两个盘子,先将小的放到b中暂存,再将大的放到c上,最后将小的放到c上
* 三个盘子,可以将问题分解成先移动上面两个到b中暂存,再将最大到放到c上,最后再将b上的放到c上,
* 而a移动到b上的过程我们已经解决过了。以此类推,因此我们可以一次次的调用自身。
*/
public static void moveTower(long dish,String from,String tmp,String to) {
if(dish==1) {
System.out.println("将盘子"+dish+"从塔台"+from+"移动到塔台"+to);
}else {
moveTower(dish-1, from, to, tmp);//将盘子n-1从a上移动到b上暂存
System.out.println("将盘子"+(dish)+"从塔台"+from+"移动到塔台"+to);
moveTower(dish-1, tmp, from, to);//将盘子n-1从b上移动到c上
}
}
public static long getWalk(long dish) { //步数
if(dish==1) {
return 1;
}else {
return 2*getWalk(dish-1)+1;
}
}
public static void main(String[] args) {
long dish = 2;
moveTower(dish,"a","b","c");
long d = getWalk(dish);
System.out.println("共移动了"+d+"步");
}
}
总结:递归虽然简单,但是解决问题的思想很重要。
常见例子
public class Recursion {
/**
* 1.递归累加
* @param n
* @return
*/
public static int sum(int n) {
if(n==1) {
return 1;
}else {
return n+sum(n-1);
}
}
/**
* 递归逆序
* @param str
* @return
*/
public static String reverse(String str) {
if(str.length()==1) {
return str;
}else {
return str.substring(str.length()-1)+reverse(str.substring(0, str.length()-1));
}
}
/**
* 十进制转二进制
* @param n
* @return
*/
public static String convert(int n) {
if(n<=1) {
return String.valueOf(n);
}else {
return convert(n/2)+n%2;
}
}
/**
*
* @param n
* @return
*/
public static int fabonacci(int n) {
if(n==1||n==2) {
return 1;
}else {
return fabonacci(n-1)+fabonacci(n-2);
}
}
public static void main(String[] args) {
System.out.println(sum(100));
System.out.println(reverse("ababababfg"));
System.out.println(convert(73));
System.out.println(fabonacci(1000));
}
}
给定一个二叉树,找到最长的路径,这个路径中的每个节点具有相同值。 这条路径可以经过也可以不经过根节点。
注意:两个节点之间的路径长度由它们之间的边数表示。
示例 1:
输入:
5
/ \
4 5
/ \ \
1 1 5
输出:
2
示例 2:
输入:
1
/ \
4 5
/ \ \
4 4 5
输出:
2
注意: 给定的二叉树不超过10000个结点。 树的高度不超过1000。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-univalue-path
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
class Solution {
int res = 0;
public int longestUnivaluePath(TreeNode root) {
helper(root);
return res;
}
int helper(TreeNode root){
if(root == null) return 0;//递归终止条件
int l = helper(root.left);//递归左子树
int r = helper(root.right);//递归右子树
l = (root.left!=null&&root.left.val==root.val)?l+1:0;//是否加一
r=(root.right!=null&&root.right.val==root.val)?r+1:0;
res = Math.max(res,l+r);//比较取最大值
return Math.max(l,r);
}
}