【问题标题】:Trouble with a stack based algorithm基于堆栈的算法的问题
【发布时间】:2013-03-01 01:01:24
【问题描述】:

我正在处理这个编程任务。它测试了我们对堆栈及其应用的理解。我发现想出一个可以高效准确工作的算法非常困难。他们的一些测试用例有 200,000 多棵“树”!虽然我的算法适用于少于 10 棵树的更简单的测试用例,但当“树”的数量非常大(从 100 多棵以上)时,它在准确性和效率方面就失败了。

如果你们能给我一个提示或指出正确的方向,我将不胜感激。谢谢。

任务说明

猴子喜欢在树间荡来荡去。他们可以从一棵树上荡秋千 只要中间没有树,就直接到另一个 高于或与两棵树中的任何一棵具有相同的高度。 例如,如果有 5 棵树,高度分别为 19m、17m、20m、20m 和 按顺序排20m,猴子就可以摆动了 从一棵树到另一棵树如下所示:

1. from first tree to second tree
2. from first tree to third tree
3. from second tree to third tree
4. from third tree to fourth tree
5. from fourth tree to fifth tree

泰山,丛林之王,能够与 猴子们,想测试一下猴子们是否会数数 他们可以直接从树上摆动的树对总数 一个对另一个。但他自己也不是很会数。所以他 轮到你,这个国家最好的 Java 程序员,写一个 获取不同部分树木的正确计数的程序 丛林。

输入

第一行包含 N,路径中的树数。下一个 行包含 N 个整数 a1 a2 a3 ... aN,其中 ai 表示 路径中第 i 棵树的高度,0

请注意,为方便起见,上面使用了短符号 N。在你的 程序,你应该给它一个描述性的名字。

输出

猴子可以摆动的树对总数 使用给定的树高列表直接从一个到另一个。

示例输入 1

4

3 4 1 2

样本输出 1

4

示例输入 2

5

19 17 20 20 20

样本输出 2

5

示例输入 3

4 1

2 21 21 12

样本输出 3

3

这是我的代码。所以这是一个返回猴子可以摆动的树对数的方法。参数是一个输入数组。

我的算法如下:

我们将 numPairs 设置为(数组长度 - 1),因为所有树都可以从一棵摇摆到另一棵。

现在我们找到了额外的 numPairs(可以用来摆动的额外树)。

将第一个输入压入空栈

我们进入一个 for 循环:

直到数组末尾的下一个输入:

案例1:

如果栈顶小于当前输入并且栈的大小等于1,那么我们用输入替换栈顶。

案例2:

如果栈顶小于当前输入且栈大小大于1,则弹出栈顶,进入while循环弹出小于当前栈顶的前一个元素.

我们在退出 while 循环后推送当前输入。

案例3:

否则,如果以上条件都不满足,我们就直接把当前输入压入栈中。

我们退出 for 循环

返回 numPairs

public int solve(int[] arr) {

    int input, temp;
    numPairs = arr.length-1;
    for(int i=0; i<arr.length; i++)
    {
        input = arr[i];

        if(stack.isEmpty())
            stack.push(input);

        else if(!stack.isEmpty())
        {
            if(input>stack.peek() && stack.size() == 1)
            {
                stack.pop();
                stack.push(input);
            }
            else if(input>stack.peek() && stack.size() > 1)
            {
                temp = stack.pop();
                while(!stack.isEmpty() && temp < stack.peek())
                {
                    numPairs++;
                    temp = stack.pop();
                }
                stack.push(input);
                //numPairs++;
            }
            else
                stack.push(input);
        }
    }
    return numPairs;
}

【问题讨论】:

  • 只是java开发的一个小技巧,尽量不要嵌套你的条件太多,也可以通过使其更递归(分而治之)来加速它。
  • 此外,您当前的方法并不贪婪,当您超过 100 多棵树时它崩溃的原因是因为您试图暴力破解每条可能的路径 (O(n^2)),如果您让它递归你可以推动 O(log(n)) 复杂性。
  • 嗯.. 明白了,嵌套是我的坏习惯。不过,我是递归的新手,只是想一想它就会让我的大脑发火……有没有更简单的基于迭代的解决方案?
  • 递归并没有你想象的那么糟糕,你只需要一个指向它完成的点(这很难,因为你不能像你认为线性时那样真正调试)。跨度>
  • 介意上传 PDF,也许还有一些示例代码?的任务,我会看看我是否可以模拟一些东西。

标签: algorithm stack


【解决方案1】:

如果我理解正确的话,有两种树可以相互访问:

  1. 彼此相邻(相邻)的树木始终可以相互访问
  2. 只有当它们之间的所有树都比两棵树都短时,才能访问不相邻的树。

人们可能会为此想出几种类型的解决方案:

  • 蛮力解决方案:将每棵树与其他每棵树进行比较,检查上述条件。运行时间:O(n^2)
  • 查找可访问的近邻解决方案:查找可访问的近邻。运行时间:接近 O(n)。以下是它的工作原理:

按照给定的顺序构建一个树大小数组。然后按顺序遍历这个数组,并为索引i 处的每棵树:

i向右走

  1. 如果i+1 的树比i 的树高(找不到更多可访问的邻居)
  2. 如果i+1 的树比i+2 的树短,则将1 添加到可访问树的计数中
  3. 对树 i+2i+3.. 等执行相同操作,直到找到比 i 处的树高的树。

这将获得每棵树的非相邻可访问树的计数。然后只需将N*2-2 添加到计数中以计算所有相邻的树,就完成了。

【讨论】:

  • 谢谢。即使我昨天解决了这个问题,但很高兴知道另一种有效的方法。 :)
  • 太棒了。也许您也想发布您的解决方案,尤其是。如果它是一个好的。
【解决方案2】:

这是我的解决方案,它是一个迭代的。

class Result {

  // declare the member field
  Stack<Integer> stack;
  int numPairs = 0;
  // declare the constructor
  public Result()
  {
    stack = new Stack<Integer>();
  }


  /* 
   * solve   : to compute the result, return the result
   *  Pre-condition : parameter must be of array of integer type
   * Post-condition : return the number of tree pairs that can be swung with
   */
  public int solve(int[] arr) {
    // implementation
    int input;

    for(int i=0; i<arr.length; i++)
    {
      input = arr[i];
      if(stack.isEmpty()) //if stack is empty, just push the input
        stack.push(input);

      else if(!stack.isEmpty())
      {
        //do a while loop to pop all possible top stack element until 
        //the top element is bigger than the input
        //or the stack is empty
        while(!stack.isEmpty() && input > stack.peek()) 
        {
          stack.pop();
          numPairs++;
        }

        //if the stack is empty after exiting the while loop
        //push the current element onto the stack
        if(stack.isEmpty())
          stack.push(input);
        //this condition applies for two cases:
        //1. the while loop is never entered because the input is smaller than the top element by default
        //2. the while loop is exited and the input is pushed onto the non-empty stack with numPairs being incremented 
        else if(!stack.isEmpty() && input < stack.peek())
        {
          stack.push(input);
          numPairs++;
        }
        //this is the last condition:
        //the input is never pushed if the input is identical to the top element
        //instead we increment the numPairs
        else if(input == stack.peek())
          numPairs++;

      }

    }
    return numPairs;
  }
}

【讨论】:

    猜你喜欢
    • 2021-10-30
    • 1970-01-01
    • 2011-03-05
    • 2011-01-09
    • 2010-10-27
    • 2011-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多