【问题标题】:? Is the result find-able in the (stair climbing/frog hops) when allowing negative integers and/or zero steps??当允许负整数和/或零步时,结果是否可以在(爬楼梯/蛙跳)中找到?
【发布时间】:2019-06-12 22:45:19
【问题描述】:

序言:

当询问楼梯问题时,通常给定的允许步数数组是 [1,2,3]

在 SO 上查看许多相同问题的示例,例如 n-steps-with-1-2-or-3-steps-taken-how-many-ways-to-get-to-the-top

我的问题与此有关,但要为允许的步数包括负数和零的情况寻找证据。

有些东西是显而易见的,例如

  • 如果所有的步长都是正数,那么可能的方法数 是有限且可解的。
  • 如果任何步长为零,则数字 可能的方式变得无限。
  • 如果至少有一个负步长 允许并且步长的任何组合总和为零,然后 可能的方式变得无限。

示例:

countSteps(stairSize:=5, [  1,2,3]) // 17
countSteps(stairSize:=5, [0,1,2,3]) // 17...

countSteps(stairSize:=5, [-2,-1  ]) // zero ways
countSteps(stairSize:=5, [-2,-1,0]) // infinitely zero ways

countSteps(stairSize:=5, [2,4]) // zero ways

countSteps(stairSize:=5, [   3]) // zero ways
countSteps(stairSize:=5, [-1,3]) // infinite ways

countSteps(stairSize:=5, [6,7,8]) // zero ways

问题:

? Can you determine whether given
    a stair size (1.. for now)
    and an array of allowable steps
    is the result find-able ?

【问题讨论】:

  • 这主要是一个数学问题(stairSize 在给定集合的加法闭包中,即stairSize 可以写成给定整数的正整数倍的总和吗?)。 This answer 到一个相关问题应该是一个不错的起点。
  • 正如您从 cmets 到我的回答中看到的那样,对于“楼梯问题”应该是什么似乎存在一些分歧。为了解决这个分歧,你能添加一个countSteps(stairSize:=5, [-1,6,7,8]) 的例子吗? (具体来说:是无限方式,还是零方式?)
  • 感谢您查看我的帖子,我没有在标题中将其作为问题提出。
  • 表达这个问题的一个困难是,最初的问题处理的是一个楼梯,它故意将问题限制在简单的情况下,因为一旦你在地面上,消极地移动不会改变你的状态。这意味着从第 3 步往下走 10 步只会让你着地,与后退 3 步完全一样。同样,从第 3 步开始向前迈步,一旦您到达着陆点,任何进一步的步骤都不会让您前进。
  • 以前在 StackOverflow stackoverflow.com/search?q=stair+1+2+3

标签: algorithm


【解决方案1】:

您可以分两部分进行:

  • 首先,创建一个大小为 stairSize 的布尔数组,表示是否可以从底部台阶到达给定台阶。将所有值初始化为“false”(包括底部步骤),然后使用搜索算法(例如 BFS 或 DFS)查找所有可到达的步骤并将它们设置为“true”。
    • 如果最上面的台阶永远不会变成“真”,那么就没有办法从底部到达最上面的台阶;返回 0。
    • 否则,如果底部步骤结束为“真”,则存在循环;返回∞。 (由于问题中的对称性,如果存在循环,底部步骤将始终以“真”结束。)
  • 接下来,创建一个大小为 stairSize 的整数数组,表示到达给定步骤的路径数。将底部步骤初始化为 1,将所有其他值初始化为 0,然后使用递归填充此数组。 (例如,这样的事情:
    private int getNumWaysToReachStep(
            final int targetStep,
            final boolean[] isStepReachable,
            final int[] numWaysToReachStep,
            final int[] numStepsAtATimeArr) {
        if (targetStep == 0) {
            return 1;
        } else if (targetStep < 0 || targetStep >= isStepReachable.length) {
            return 0;
        } else if (numWaysToReachStep[targetStep] != 0 || ! isStepReachable[targetStep]) {
            return numWaysToReachStep[targetStep];
        }
        int result = 0;
        for (final int numSteps : numStepsAtATimeArr) {
            result += getNumWaysToReachStep(targetStep - numSteps, isStepReachable,
                          numWaysToReachStep, numStepsAtATimeArr);
        }
        numWaysToReachStep[targetStep] = result;
        return result;
    }
    
    )

总的来说,这需要 O(stairSize ·|numStepsAtATimeArr|) 时间和 O( stairSize) 额外的空间。

【讨论】:

  • 不幸的是,这个解决方案中的数组大小没有很好的上限。考虑一个有效的步骤数组,如[-1, MAX_INT];每一步都是可以到达的,但大多数只能从顶部到达(除非有一个大地下室可以让你在让你的大MAX_INT 上楼之前下楼)。
  • @CraigMeier:我不确定你的意思。问题的目标是找到从底部到顶部的方法的数量。当数组的大小实际上只是 stairSize 时,你很难声称“数组大小没有好的上限”。
  • stairSize=5 和有效步骤[6,7,8] 的示例让我相信stairSize 实际上是指楼梯中的目标楼梯,具有任意数量的楼梯,而不是楼梯的总大小。否则,是的,如果stairSize 是顶部步骤的索引,那么数组只需要调整大小stairSize + 1
  • @CraigMeier:哦,我明白了。我以stairSize=5 和有效步骤[6,7,8] 为例,表示实际上没有步骤是可能的,因为楼梯对于任何选项都不够高。我猜 OP 没有明确指出“楼梯问题”是什么,但他将 stackoverflow.com/questions/22562023/… 描述为“同样的问题”,并且明确表明这是关于到达 top楼梯。
猜你喜欢
  • 1970-01-01
  • 2020-11-09
  • 1970-01-01
  • 2021-09-18
  • 1970-01-01
  • 2015-10-11
  • 1970-01-01
  • 2016-07-01
  • 1970-01-01
相关资源
最近更新 更多