【问题标题】:Maximum height of the staircase楼梯最大高度
【发布时间】:2020-02-19 13:06:12
【问题描述】:

给定一个表示正方形块的整数 A。每个方块的高度为 1。任务是使用这些方块创建一个最大高度的楼梯。第一个楼梯只需要一个街区,第二个楼梯需要两个街区,依此类推。查找并返回楼梯的最大高度。


您的提交因以下输入而失败:A : 92761

您的函数返回以下内容:65536
预期返回值:430

Approach:
We are interested in the number of steps and we know that each step Si uses exactly Bi number of bricks. We can represent this problem as an equation:
n * (n + 1) / 2 = T (For Natural number series starting from 1, 2, 3, 4, 5 …)
n * (n + 1) = 2 * T
n-1 will represent our final solution because our series in problem starts from 2, 3, 4, 5…

Now, we just have to solve this equation and for that we can exploit binary search to find the solution to this equation. Lower and Higher bounds of binary search are 1 and T.

代码

public int solve(int A) {
        int l=1,h=A,T=2*A;
        while(l<=h)
        {
            int mid=l+(h-l)/2;
            if((mid*(mid+1))==T)  
                return mid;
            if((mid*(mid+1))>T && (mid!=0 && (mid*(mid-1))<=T) )
                return mid-1;
            if((mid*(mid+1))>T)
                h=mid-1;
            else
                l=mid+1;
        }
        return 0;
    }

【问题讨论】:

  • 您的问题是,当您以 92761 开头时,mid*(mid+1) 将大于最大可能整数并变为负值。改为 long 而不是 int。
  • 在楼梯上,A = h(h+1)/2,所以 h^2 + h =2A。求解得到 h = (sqrt(8A+1)-1)/2。不需要循环。
  • @MattTimmermans 您应该将其发布为答案。
  • 如果你想用二分搜索来解决这个问题,你可以从你的下限开始加快速度,等于sqrt(A)。但一个更好的解决方案是 Matt Timmermans 在他的评论中提出的。我在答案中添加了一些细节。

标签: java data-structures binary-search


【解决方案1】:

扩展 Matt Timmermans 的评论:

您知道对于n 步骤,您需要(n * (n + 1))/2 块。你想知道,如果给定B 块,你可以创建多少个步骤。

所以你有:

(n * (n + 1))/2 = B
(n^2 + n)/2 = B
n^2 + n = 2B
n^2 + n - 2B = 0

这看起来有点像你会使用 quadratic formula 的东西。

在这种情况下,a=1b=1c=(-2B)。将数字代入公式:

n = ((-b) + sqrt(b^2 - 4*a*c))/(2*a)
  = (-1 + sqrt(1 - 4*1*(-2B)))/(2*a)
  = (-1 + sqrt(1 + 8B))/2
  = (sqrt(1 + 8B) - 1)/2

所以如果你有 5050 个区块,你会得到:

n = (sqrt(1 + 40400) - 1)/2
  = (sqrt(40401) - 1)/2
  = (201 - 1)/2
  = 100

试试quadratic formula calculator。使用 1 作为 a 和 b 的值,并将 c 替换为给定块数的两倍的负数。所以在上面的例子中,c 是 -10100。

在您的程序中,由于您不能有部分步骤,因此您需要截断结果。

【讨论】:

    【解决方案2】:

    您为什么要使用所有这些公式?一个简单的while() 循环应该可以解决问题,最终,它只是一个简单的高斯和..

    public static int calculateStairs(int blocks) {
        int lastHeight = 0;
        int sum = 0;
        int currentHeight = 0; //number of bricks / level
        while (sum <= blocks) {
            lastHeight = currentHeight;
            currentHeight++;
            sum += currentHeight;
        }
        return lastHeight;
    }
    

    【讨论】:

    • 当您可以通过应用一些简单的数学来解决问题时,为什么还要进行所有迭代?虽然您的简单 while 循环更容易编码,但二进制搜索会快得多。
    • 顺便问一下,为什么最后是Math.minlastHeight 将始终小于或等于 currentHeight。您可以重构代码以消除lastHeight,并消除流程中的一次循环迭代。
    • 没错:(我的错误。我提供了一个解决方案,有很多。但是当然,您的方法要容易得多,谢谢先生!
    【解决方案3】:

    所以这应该可以完成工作,因为它还返回预期值。如果我错了,请纠正我。

    public int solve(int blocks) {
        int current; //Create Variables
        for (int x = 0; x < Integer.MAX_VALUE; x++) { //Increment until return
          current = 0; //Set current to 0
    
            //Implementation of the Gauss sum
            for (int i = 1; i <= x; i++) { //Sum up [1,*current height*]
                current += i;
            } //Now we have the amount of blocks required for the current height
    
            //Now we check if the amount of blocks is bigger than
            // the wanted amount, and if so we return the last one
            if (current > blocks) {
                return x - 1;
            }
        }
        return current;
    }
    

    【讨论】:

    • 从 0 迭代的目的是什么?这不是最好的解决方案,但是是的,它返回了预期值。甚至没有使用 last 变量。
    • 你的权利错了。在我将它替换为 x - 1 之后,我忘记了删除它。从 0 开始迭代也是一件愚蠢的事情,因为它是一次无用的迭代。我只是为“fori”使用了代码生成,然后就这样离开了
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-12-24
    • 1970-01-01
    • 2020-08-03
    • 2015-05-29
    • 1970-01-01
    • 2015-02-22
    • 1970-01-01
    相关资源
    最近更新 更多