因此,我已经构建了该程序来构建不同的楼梯案例。本质上,问题是:给定整数N,您可以建立楼梯的几种不同方式。确保N大于3且小于200。任何先前的步骤都不能大于其后续步骤,否则会破坏楼梯的目的。
所以给定N = 3,您可以建立一个楼梯:2步,然后再步1步
给定N = 4,您可以建立一个楼梯:3步,然后再步1步
给定N = 5,您可以构建两个楼梯:3步,然后2步,或4步,然后1步。
我的方法在下面,并且可以运行,除了它的运行速度太慢之外。因此,我当时正在考虑为该方法做一个记录,但是老实说,我并不完全了解如何实现该方法。如果我能在这方面获得一些帮助,那就太好了。
public static void main(String [] args)
{
System.out.println(answer(200));
}
public static int answer(int n) {
return bricks(1,n) -1;
}
public static int bricks(int height, int bricksLeft)
{
if(bricksLeft == 0)
{
return 1;
}
else if(bricksLeft < height)
{
return 0;
}
else
{
return bricks(height +1, bricksLeft - height) + bricks(height +1, bricksLeft);
}
}
总览
因此,这里有一个递归解决方案。这对于此类问题非常有效。在此特定的递归解决方案中,您的递归步骤将多次使用相同的参数调用。
对于多次进行相同计算的递归解决方案,一种真正常见的优化模式是动态编程。这个想法是,与其多次进行相同的计算,我们只是在第一次执行时对每个计算进行缓存。然后每隔一段时间,如果我们需要计算完全相同的值,就可以从缓存中读取结果。
解
考虑到这一点,此解决方案应该有效。它使用与原始版本完全相同的逻辑,只是将递归步骤中的所有结果缓存在中,HashMap
这样就永远不需要两次计算相同的东西。它还使用一个Staircase
对象来跟踪(砖,高度)对。这是因为我们不能在中插入对HashMap
,而只能插入单个对象。
只需将变量更改为bricks
您想要解决的任何值即可。
public class Staircase {
private static HashMap<Staircase, Integer> cache;
public static void main(String[] args) {
cache = new HashMap<>();
int bricks = 6;
Staircase toBuild = new Staircase(1, bricks);
System.out.println(toBuild.waysToBuild() - 1);
}
public final int height;
public final int bricksLeft;
public Staircase(int height, int bricksLeft) {
this.height = height;
this.bricksLeft = bricksLeft;
}
public int waysToBuild() {
if (cache.containsKey(this)) {
return cache.get(this);
}
int toReturn;
if (bricksLeft == 0) {
toReturn = 1;
} else if (bricksLeft < height) {
toReturn = 0;
} else {
Staircase component1 = new Staircase(height + 1, bricksLeft - height);
Staircase component2 = new Staircase(height + 1, bricksLeft);
toReturn = component1.waysToBuild() + component2.waysToBuild();
}
cache.put(this, toReturn);
return toReturn;
}
@Override
public boolean equals(Object other) {
if (other instanceof Staircase) {
if (height != ((Staircase) other).height) {
return false;
}
if (bricksLeft != ((Staircase) other).bricksLeft) {
return false;
}
return true;
}
return false;
}
@Override
public int hashCode() {
int hash = 5;
hash = 73 * hash + this.height;
hash = 73 * hash + this.bricksLeft;
return hash;
}
}
分析
我对其进行了测试,其性能比以前的版本要快得多。它可以立即计算多达200个值。
您原来的功能是O(2^n)
。那是因为我们对从1
到的每个值进行2次递归调用n
,因此每次n递增时,调用的总数就会增加一倍。
动态编程解决方案是O(n)
因为最多需要n
为的每个值计算一次用砖砌成楼梯的方法数量n
。
附加阅读
以下是有关动态编程的更多信息:https :
//en.wikipedia.org/wiki/Dynamic_programming
问题内容: 我在使用Java中的基本递归问题时遇到了很多麻烦;任何指针都很棒。 “写一种静态递归方法来打印出几何序列的第n个项:2、6、18、54。” 据我所知,我应该在代码中的某处递归地将某物乘以3,但我一直在努力寻找方法。我知道我需要终止声明,但是何时发生?我需要帮手方法吗? 问题答案: 一个递归函数是一个函数,它的实现引用自身。以下是一些有趣的示例: 解决问题的方法: 编辑 : 上面的类使用
问题内容: 我有一个程序可以通过递归传递大量数据,例如1000个变量。递归将至少运行50或60次。我担心的是,由于没有足够的空间,是否有可能数据在内存位置上被覆盖,或者如果没有内存,那么我会得到一些例外,即程序内存已经用完(我没有收到这样的错误)? 是否存在错误的解决方案,因为该程序没有更多的内存并且在现有位置上被覆盖? 问题答案: 涉及两个存储区域:堆栈和堆。堆栈是保存方法调用的当前 状态 (即
我的应用程序中有一个名为posts的实体。帖子可以是其他帖子的子帖子,因此父帖子有hasMany('Posts'),子帖子有hasOne('post')。包含是无限的。 以下是模式: 如何递归地获取“Post_id”设置为null的第一篇帖子的所有子帖子和子帖子的子帖子等? 请不要在这里评论性能,我知道这样的模式很糟糕,我只想知道如何正确编写递归函数来检索无限嵌套的帖子。
问题内容: 如何递归所有目录和子目录? 问题答案: 第一个参数表示要搜索的正则表达式,而第二个参数表示应搜索的目录。在这种情况下,表示当前目录。 注意:这适用于GNU grep,在某些平台(如Solaris)上,必须专门使用GNU grep而不是传统实现。对于Solaris,这是命令。
我有两个非递归方法,其中一个读取字符串中的总“e”字符,另一个检查 ArrayList 是否按字母顺序排列。 递归方法的定义是方法调用自身。我相信我理解这个概念,但要实现它或将其转换为递归方法确实很困难。我怎样才能将这些方法转化为递归方法,同时我应该如何思考?此外,这是我的另一种方法,它只打印出指定数字大小的数字。 条件方法检查数字的第一个数字(从右起)是否大于第二个数字,并再次检查第二个是否大于
我正在处理我当前的任务,即创建一个LinkedList数据结构,我已经创建了它以及其他方法,它工作得非常好。我正在处理我的最后一个问题,即制作一个toString方法。它应该: toString方法返回列表的字符串表示形式。用逗号分隔每个项目,并用大括号括住这些项目,例如{1,4,7,5}。公共toString方法必须调用私有递归方法来生成以逗号分隔的项目列表。(但您可以在公共方法中添加大括号。)