常见的一道算法题:

一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶。求该青蛙跳上一个 n 级的台阶总共有多少种跳法。

解法我想很多人一想应该就知道,可以递归的思路,动态规划的思路等,代码如下,重点不在这里,不在详述:

//递归
public static int frogJumps_1(int n) {if(n==0) return 1;if(n==1) return 1;return frogJumps_1(n-1) + frogJumps_1(n-2);
}
//带备忘录的递归
public static int frogJumps_2(int n) {int[] memo = new int[n+1];return helper(n, memo);}private static int helper(int n, int[] memo) {if(n==0) return 1;if(n==1) return 1;if(memo[n]!=0)return memo[n];memo[n] = frogJumps_2(n-1) + frogJumps_2(n-2);return memo[n];}
//dp,貌似也算不上dp问题,没有求最值
public static int frogJumps_3(int n) {int[] dp = new int[n+1];dp[0] = 1;dp[1] = 1;for(int i=2; i<dp.length; i++) {dp[i] = dp[i-1] + dp[i-2];}return dp[n];}

但是前几天遇到一个问题,要打印出青蛙跳台所有的可能路径,例如:

输入 :n = 3
输出 :1111221

网上没有找到相关解法,目前想了个算法打印出所有路径,不一定是最好的,有更好的欢迎指正。思路如下:

若求f(n),画出递归树的时候,这就是一个二叉树,而二叉树的从下到上的所有路径就是青蛙跳台的所有可能路径,并且如果左子树是f(n-1),右子树是f(n-2),那么从左子树走到顶点就是走一步,从右子树走到顶点就是走两步。

所以算法步骤如下,通过dp数组构造一个二叉树,然后打印二叉树的所有路径即可输出青蛙跳台的所有可能路径。

代码如下:

public static int frogJumps_4(int n) {Node[] dp = new Node[n+1];dp[0] = new Node(1, null, null);dp[1] = new Node(1, dp[0], null);for(int i=2; i<dp.length; i++) {dp[i] = new Node(dp[i-1].val + dp[i-2].val, dp[i-1], dp[i-2]);}//打印出二叉数所有路径printTree(dp[n], n);return dp[n].val;}private static void printTree(Node root, int n) {int[] path = new int[n+1];printPath(root, path, 0, 0);}private static void printPath(Node node, int[] path, int n, int pos) {if(node==null) return;path[n++] = pos;if(node.left==null && node.right==null) {for (int i = 1; i < n; i++)System.out.print(path[i]);System.out.println();} else {printPath(node.left, path, n, 1);printPath(node.right, path, n, 2);}}private static class Node {int val;Node left;Node right;public Node(int val, Node left, Node right) {this.val = val;this.left = left;this.right = right;}}

还有个青蛙跳台变形的题,说青蛙不是只可以跳一步和两步,可以跳任意步到达终点,如果问有多少种方式,其实推导出来就是f(n)=2f(n-1),照着上面代码写就好了,很简单。

如果也让打印出所有路径,例如:

输入 :n = 3
输出 :11112213

按目前思路可能就处理更复杂了,要用到多叉树,然后打印出多叉树的所有路径,代码如下:

public static int frogJumps_5(int n) {Node1[] dp = new Node1[n+1];dp[0] = new Node1(1, 0);dp[1] = new Node1(1, 1);dp[1].add(dp[0], 0);for(int i=2; i<dp.length; i++) {dp[i] = new Node1( 2 * dp[i-1].val, i);for(int j=i-1; j>=0; j--) {dp[i].add(dp[j], i-1-j);}}//打印出二叉数所有路径printMultiTree(dp[n], n);return dp[n].val;}private static void printMultiTree(Node1 root, int n) {int[] path = new int[n+1];printMultiPath(root, path, 0, 0);}private static void printMultiPath(Node1 node, int[] path, int n, int pos) {if(node==null) return;path[n++] = pos;if(node.nodes.length==0) {for (int i = 1; i < n; i++)System.out.print(path[i]);System.out.println();} else {for(int i=0; i<node.nodes.length; i++) {printMultiPath(node.nodes[i], path, n, i+1);}}}private static class Node1 {int val;Node1[] nodes;public Node1(int val, int n) {this.val = val;nodes = new Node1[n];}public void add(Node1 node, int index) {nodes[index] = node;}}

全部代码如下:

public class MaximumFrogJumps {public static void maximumFrogJumps(int n) {//暴力解法System.out.println(frogJumps_1(n));//添加备忘录System.out.println(frogJumps_2(n));//dpSystem.out.println(frogJumps_3(n));//打印路路径System.out.println(frogJumps_4(n));//打印路路径System.out.println(frogJumps_5(n));}public static int frogJumps_1(int n) {if(n==0) return 1;if(n==1) return 1;return frogJumps_1(n-1) + frogJumps_1(n-2);}public static int frogJumps_2(int n) {int[] memo = new int[n+1];return helper(n, memo);}private static int helper(int n, int[] memo) {if(n==0) return 1;if(n==1) return 1;if(memo[n]!=0)return memo[n];memo[n] = frogJumps_2(n-1) + frogJumps_2(n-2);return memo[n];}public static int frogJumps_3(int n) {int[] dp = new int[n+1];dp[0] = 1;dp[1] = 1;for(int i=2; i<dp.length; i++) {dp[i] = dp[i-1] + dp[i-2];}return dp[n];}public static int frogJumps_4(int n) {Node[] dp = new Node[n+1];dp[0] = new Node(1, null, null);dp[1] = new Node(1, dp[0], null);for(int i=2; i<dp.length; i++) {dp[i] = new Node(dp[i-1].val + dp[i-2].val, dp[i-1], dp[i-2]);}//打印出二叉数所有路径printTree(dp[n], n);return dp[n].val;}private static void printTree(Node root, int n) {int[] path = new int[n+1];printPath(root, path, 0, 0);}private static void printPath(Node node, int[] path, int n, int pos) {if(node==null) return;path[n++] = pos;if(node.left==null && node.right==null) {for (int i = 1; i < n; i++)System.out.print(path[i]);System.out.println();} else {printPath(node.left, path, n, 1);printPath(node.right, path, n, 2);}}private static class Node {int val;Node left;Node right;public Node(int val, Node left, Node right) {this.val = val;this.left = left;this.right = right;}}public static int frogJumps_5(int n) {Node1[] dp = new Node1[n+1];dp[0] = new Node1(1, 0);dp[1] = new Node1(1, 1);dp[1].add(dp[0], 0);for(int i=2; i<dp.length; i++) {dp[i] = new Node1( 2 * dp[i-1].val, i);for(int j=i-1; j>=0; j--) {dp[i].add(dp[j], i-1-j);}}//打印出二叉数所有路径printMultiTree(dp[n], n);return dp[n].val;}private static void printMultiTree(Node1 root, int n) {int[] path = new int[n+1];printMultiPath(root, path, 0, 0);}private static void printMultiPath(Node1 node, int[] path, int n, int pos) {if(node==null) return;path[n++] = pos;if(node.nodes.length==0) {for (int i = 1; i < n; i++)System.out.print(path[i]);System.out.println();} else {for(int i=0; i<node.nodes.length; i++) {printMultiPath(node.nodes[i], path, n, i+1);}}}private static class Node1 {int val;Node1[] nodes;public Node1(int val, int n) {this.val = val;nodes = new Node1[n];}public void add(Node1 node, int index) {nodes[index] = node;}}
}

输入3运行结果如下:

3
3
3
111
12
21
3
111
12
21
3
4

============================================
2020.05.14 更新
今天学习了回溯算法,发现这个题回溯算法解也太简单了,唉…

 //跳一步或者两步private static void frogJumps_6(int n) {LinkedList<Integer> res = new LinkedList<Integer>();int[] nums = new int[]{1, 2};backtrack(nums, n, res);}//跳任意步private static void frogJumps_7(int n) {LinkedList<Integer> res = new LinkedList<Integer>();int[] nums = new int[n];for(int i=0; i<nums.length; i++) {nums[i] = i+1;}backtrack(nums, n, res);}private static void backtrack(int[] nums, int n, LinkedList<Integer> res) {if(n==0) {System.out.println(res);return;}if(n<0)return;for(int i=0; i<nums.length; i++) {res.add(nums[i]);backtrack(nums, n-nums[i], res);res.removeLast();}}

输出青蛙跳台所有路径相关推荐

  1. 青蛙跳台(含变种)及汉诺塔递归,母牛生小牛

    青蛙跳台(含变种)及汉诺塔递归,母牛生小牛 文章目录 青蛙跳台(含变种)及汉诺塔递归,母牛生小牛 #define _CRT_SECURE_NO_WARNINGS #include<Windows ...

  2. java log输出到文件路径_log4j中日志输出文件指定相对路径的方法

    log4j中日志输出文件指定相对路径的方法 1.设置在 C:/log/error.log log4j.appender.E = org.apache.log4j.RollingFileAppender ...

  3. 斐波那契数列的编程题,青蛙跳台

    斐波那契数列的编程题,青蛙跳台 一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶.求该青蛙跳上一个 n 级的台阶总共有多少种跳法. 答案需要取模 1e9+7(1000000007),如计算初始结果为: ...

  4. 青蛙跳台(递归和非递归实现)

    青蛙跳台 一.问题描述: 二.问题分析: 三.代码实现: 1.递归实现: 2.非递归实现: 四.问题进阶: 1.问题分析: 2.代码实现: 一.问题描述: 一只青蛙一次可以跳上1级台阶,也可以跳上2级 ...

  5. C语言:青蛙跳台与汉诺塔问题

    青蛙跳台 原理:一只青蛙跳n个台阶,青蛙可以一次性跳1个台阶,也可以跳2个台阶,问,有多少种跳法,可以跳过n个台阶. 分析:青蛙跳台本质上是递归问题,那它为什么是递归问题呢? ①假如有一个台阶,那青蛙 ...

  6. 青蛙跳台问题(初级)

    1.问题引入: 一只青蛙一次可以跳上1级台阶,也可以跳上2级.求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果). 2.逆向思维: 设跳到n上有P(n)种可能  青蛙最后一步前在第 ...

  7. C++ 输出当前所在的路径

    C++ 输出当前项目路径 我的小站.Github.CSDN 代码: #include <iostream> #include <filesystem> using namesp ...

  8. java 输出文件到mac路径_javamac的文件路径怎么写

    1. java mac 安装路径在哪 1. Mac OS自带的JDK 6:/System/Library/Frameworks/JavaVM.framework/Versions/Current/Co ...

  9. java 输出文件到mac路径_Java 中几种获取文件路径的方式

    原标题:Java 中几种获取文件路径的方式 1. 前言 Java开发中我们经常要获取文件的路径,比如读取配置文件等等.今天我们就关于文件的路径和如何读取文件简单地探讨一下. 2. 文件的路径 文件的路 ...

最新文章

  1. 开源自制6通道航模遥控器,Arduino Pro Mini NRF24L01模块
  2. Linux下安装jdk8步骤详述
  3. C语言 数据结构 树和二叉树
  4. HashMap原理解析
  5. java web 加载类_Tomcat类加载机制
  6. java调用hp打印机驱动_惠普打印机驱动修改JDK问题–现象:javac不能用了 | 学步园...
  7. c语言中cnthe普通变量,不得不说,关于 *(unsigned long *) 和 (unsigned long)
  8. 30天自己制作操作系统中二进制编辑器BZ-1621
  9. Mybatis+Servlet+jsp
  10. ESlint配置大全
  11. 六类双绞线排序和信息插座排序
  12. 文件夹中的文件在另一程序被打开
  13. 5个拍出可爱宝宝的方法
  14. 不等于在python中怎么表示_python中的不等于怎么写
  15. 通用漏洞评分系统 (CVSS)系统入门指南
  16. Html监听Fbx文件加载,Three.js 导入fbx
  17. 前端在线js文件避免下包,(练手)
  18. .net core 使用 Hangfire 实现定时、延时任务
  19. 大数据hadoop集群运算
  20. 2022年双十一洗面奶选购指南

热门文章

  1. 简单网页版的注册登录案例(JSP+CSS+MySQL+Servlet+MVC设计思想,含源码!)
  2. 心跳包机制及Socket通信服务的心跳包
  3. libxml2对XML文件的创建、解析、查找、修改
  4. 论文阅读笔记(7-1)---Supervised Contrastive Learning
  5. SVPWM控制技术+Matlab/Simulink仿真详解
  6. src refspec xxx does not match any 错误处理办法
  7. linux aio进程简介,Linux AIO机制
  8. synchronized同步锁原理详解
  9. photoswipe 移动端PC端兼容图片相册预览
  10. 用批处理文件检测u盘并进行复制