递归

递归

       方法调用自己本身,叫递归

三个要素

  • 边界条件
  • 递归前进段
  • 递归返回段

例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);
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值