计算(不是设计!)Java中堆栈的最小值

计算(不是设计!)Java中堆栈的最小值,java,stack,time-complexity,Java,Stack,Time Complexity,我想写一个函数来计算给定堆栈的最小值。我以为我可以在网上很容易地找到,但我什么也没找到。我所发现的就是如何用getMinimum函数设计堆栈 不同之处在于,当您设计这样一个堆栈时,您将逐渐构造堆栈(推送和弹出),并在任何操作后更新最小值。我在想,如果你有一个给定的堆栈,你想计算这个堆栈的最小值,你怎么处理呢?也许,我没有很好地进行推理,或者我问自己错误的答案,或者我不太理解堆栈的概念,但让我惊讶的是,即使经过大量搜索,在网上也找不到任何关于堆栈的答案 以下是我的尝试: public st

我想写一个函数来计算给定堆栈的最小值。我以为我可以在网上很容易地找到,但我什么也没找到。我所发现的就是如何用getMinimum函数设计堆栈

不同之处在于,当您设计这样一个堆栈时,您将逐渐构造堆栈(推送和弹出),并在任何操作后更新最小值。我在想,如果你有一个给定的堆栈,你想计算这个堆栈的最小值,你怎么处理呢?也许,我没有很好地进行推理,或者我问自己错误的答案,或者我不太理解堆栈的概念,但让我惊讶的是,即使经过大量搜索,在网上也找不到任何关于堆栈的答案

以下是我的尝试:

    public static int min(Stack stack){
        Stack temp = new Stack();
        int result = Integer.MAX_VALUE;
        while(!stack.isEmpty()) {
                int value = stack.pop();
                temp.push(value);
                result =  (result >= value)? value : result;
            }
    //stack is empty now, I have to recuperate it from the temp stack
             while(!temp.isEmpty()) {
                     stack.push(temp.pop());
             }

             return result;
      }
在这段代码中,我使用自己的堆栈和节点实现。但正如您所看到的,代码非常简单。我写这篇文章主要是因为我问了自己很多问题

特别是,我想问你三个主要问题:

  • 此函数的时间和空间复杂度是多少?我想是O(N),对吗?在我的程序中,我总是会遇到一些计算困难。它通常是O(2*N)(等于O(N)),因为我们在每个节点上运行堆栈节点
  • 我的方法是否合乎逻辑?据我所知,如果您想访问堆栈中的第k个元素,必须弹出k-1 previous元素。或者在这里,在我看来,如果我们只想计算它的最小值(如果你想再次操作同一个堆栈),那么弹出整个堆栈是绝对不符合逻辑的。这就是为什么我做了第二个while循环以保持堆栈处于其原始状态
  • 也许,我们可以复制一个堆栈,但我读到用Java克隆对象并不是那么容易,我想知道对于这样一个小功能来说,克隆对象是否会非常耗时
谢谢

  • 正如你所解释的,时间和空间确实是O(n)

  • 你的方法有逻辑性。但是,您可以以这样一种方式实现堆栈,即允许您实现peek(int-index)-(例如,如果您的堆栈基于数组),然后您就不必重新插入所有元素

  • 您可以在堆栈实现中保存额外的排序数据结构,这将允许您获取O(1)中的最小值,但将使用的空间增加一倍。最后,它总是在空间和时间之间进行权衡


  • 使用递归会容易得多:

    int min(Stack stack) {
        if(stack.isEmpty())
            return Integer.MAX_VALUE;
    
        int temp = stack.pop();
        int min = Math.min(temp, min(stack));
        stack.push(temp);
    
        return min;
    }
    

    在我看来,一个更好的选择是利用
    Vector
    能力,因为
    Stack
    是Java中
    Vector
    的一个子类

    public static int min(Stack<Integer> stack) {
        Integer[] elements = stack.toArray(new Integer[1]);
        int min = Integer.MAX_VALUE;
        for(int i=0;i<elements.length;i++) {
            if(elements[i] < min) {
                min=elements[i];
            }
        }
        return min;
    }
    
    publicstaticintmin(堆栈){
    整数[]元素=stack.toArray(新整数[1]);
    int min=整数最大值;
    
    对于(int i=0;i,Java中的堆栈类继承自Vector。因此,您只需枚举项,而无需执行任何推送、弹出或复制操作。因此,这里有一个O(N)解决方案:

    public static int min(Stack stack) {
        int m = Integer.MAX_VALUE;
        for (int i = 0; i < stack.size(); i++) {
    
            int current = stack.get(i).intValue();
    
            if (current < m)
            {
                 m = current;
            }
        }
        return m;
    }
    
    publicstaticintmin(堆栈){
    int m=整数最大值;
    对于(int i=0;i
    此外,如果您不想修改“addToStack”函数,您无法真正改进此min函数,因此,是的,您的解决方案也是我所尝试的。我还想说,复杂性是O(n)Euh,我在我的IDE中尝试过这一点,它是有效的。但老实说,这并不是真的计算min(它可以是max或其他任何东西)。更多的是了解堆栈概念背后的概念和实用程序:)是的,是的,是的(永远不要使用克隆,我怀疑您的攻击类是否合理地实现了它)。此外,这在代码审查方面确实会更好,但总体思路是合理的。@salamanka44如果您能提供完整的代码示例,我可以更好地查看它。就像整个文件+堆栈一样。如果您能获得堆栈并使用java 8,您只需执行..
    System.out.println(Arrays.stream(nums.min().getAsInt());
    当使用一个巨大的堆栈时,这个解决方案不会崩溃吗?这难道不容易导致“太多递归”错误吗?@Dodekeract当然,CS中没有免费的午餐。一个更正。我不认为
    []
    操作符过载。而不是
    元素[I]
    说,
    元素。get(I)
    这是一个数组,只能使用
    []
    访问数组。请看第一行。关于为什么要用
    堆栈复制数组。toArray
    ?只需从
    0..stack.size()-1中枚举即可。我将发布一个答案来说明我的意思。