如何在不使用max()或迭代它的情况下在堆栈中查找最大整数值?

c12*_*c12 19 java

我在接受采访时被问到以下问题:如果你有一个整数堆栈,你如何在不使用Collections.max的情况下找到堆栈的最大值,而不是迭代堆栈并比较元素.我用下面的代码回答它,因为我不知道使用任何Collections API或迭代Stack并使用比较的另一种方式.有任何想法吗?

import java.util.Collections;
import java.util.Stack;

public class StackDemo {
    public static void main(String[] args){
        Stack lifo = new Stack();
        lifo.push(new Integer(4));
        lifo.push(new Integer(1));
        lifo.push(new Integer(150));
        lifo.push(new Integer(40));
        lifo.push(new Integer(0));
        lifo.push(new Integer(60));
        lifo.push(new Integer(47));
        lifo.push(new Integer(104));

        if(!lifo.isEmpty()){
            Object max = Collections.max(lifo);
            System.out.println("max=" + max.toString());
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Dan*_*yMo 31

通过使用Collections.min()代替:

if (!lifo.isEmpty()) {
  Integer max = Collections.min(lifo, new Comparator<Integer>() {
    @Override
    public int compare(Integer o1, Integer o2) {
      return o2.compareTo(o1);
    }
  });
  System.out.println("max=" + max.toString());
}
Run Code Online (Sandbox Code Playgroud)

请注意,自定义Comparator翻转比较,以便Collections.min()实际返回最大值.

  • @HenryKeiter你可能是对的,但我无法放弃成为聪明屁股的机会! (12认同)
  • 我不相信这是挑战的精神,但我喜欢实施:D (10认同)
  • 如果这不是一个令人讨厌的问题,我会说这是一个令人讨厌的答案......但在上下文中,它是完美的. (6认同)

end*_*and 11

import java.util.Collections;
import java.util.Stack;

public class StackDemo {
    public static void main(String[] args) {
        Stack lifo = new Stack();
        lifo.push(new Integer(4));
        lifo.push(new Integer(1));
        lifo.push(new Integer(150));
        lifo.push(new Integer(40));
        lifo.push(new Integer(0));
        lifo.push(new Integer(60));
        lifo.push(new Integer(47));
        lifo.push(new Integer(104));

        System.out.println("max= 150"); // http://xkcd.com/221/
    }
} 
Run Code Online (Sandbox Code Playgroud)


Smi*_*mit 10

不确定这是否满足您的问题需求,但这种方式的使用max()iteration可以避免,无论如何sort确实使用iterationComparable 在后台.

if (!lifo.isEmpty()) {
    Stack sc = (Stack) lifo.clone();
    Collections.sort(sc);
    System.out.println("max=" + sc.get(sc.size() - 1));
}
Run Code Online (Sandbox Code Playgroud)

  • @ c12你的问题应该反映这一点. (2认同)

Luk*_*uke 9

编辑:

没有遍历堆栈

实际上并没有禁止所有迭代.相反,这个问题只是禁止做简单的事情

for (Integer i : lifo)
Run Code Online (Sandbox Code Playgroud)

因此,该解决方案满足了问题的局限性.


只是清空堆栈的副本.弹出副本中的每个元素,始终检查max与整数.

Stack<Integer> lifoCopy = (Stack<Integer>) lifo.clone();
int max = Integer.MIN_VALUE;

while (!lifoCopy.isEmpty())
{
    max = Math.max(lifoCopy.pop(), max);
}

System.out.println("max=" + max.toString());
Run Code Online (Sandbox Code Playgroud)

这将在O(n)时间内为您工作,即使您的采访者决定更具限制性并且不允许更多内置功能(最大,最小,排序等).

此外,如果您需要原始安全,但不能使用克隆,您可以使用额外的堆栈:

Stack<Integer> reverseLifo = new Stack<Integer>();
int max = Integer.MIN_VALUE;

while (!lifo.isEmpty())
{
    int val = lifo.pop();

    max = Math.max(val, max);

    reverseLifo.push(val);
}

while (!reverseLifo.isEmpty())
{
    lifo.push(reverseLifo.pop());
}

System.out.println("max=" + max.toString());
Run Code Online (Sandbox Code Playgroud)

最后,这假设可以接受与temp变量的比较.如果根本不允许比较,则此解决方案与此方法一起使用.

  • 这怎么不"迭代堆栈"? (24认同)

lin*_*ski 7

这段代码:

public static Integer max(Stack stack) {
    if (stack.isEmpty()) {
        return Integer.MIN_VALUE;
    }
    else {
        Integer last = (Integer)stack.pop();
        Integer next = max(stack);
        stack.push(last);
        if (last > next) {
            return last;
        }
        else {
            return next;
        }            
    }
}

public static void main(String[] args){
    Stack lifo = new Stack();
    lifo.push(new Integer(4));
    lifo.push(new Integer(1));
    lifo.push(new Integer(150));
    lifo.push(new Integer(40));
    lifo.push(new Integer(0));
    lifo.push(new Integer(60));
    lifo.push(new Integer(47));
    lifo.push(new Integer(104));

    System.out.println(Arrays.deepToString(lifo.toArray()));
    System.out.println(max(lifo));
    System.out.println(Arrays.deepToString(lifo.toArray()));
}
Run Code Online (Sandbox Code Playgroud)

输出:

[4, 1, 150, 40, 0, 60, 47, 104]
150
[4, 1, 150, 40, 0, 60, 47, 104]
Run Code Online (Sandbox Code Playgroud)

它是给定堆栈的递归,找到最大元素并且不会更改堆栈顺序.

但是,只有在您定义迭代时,迭代才与递归不同.此外,要找到最大值,你必须以某种方式比较所有元素 - 无论以何种数学形式,与Anirudh 表示的关系或按位运算符.恕我直言,相当模糊的任务.

  • 我同意这个问题的模糊性.有些术语需要在上下文中明确定义,以便可以解决. (4认同)

Ani*_*dha 6

您可以使用按位运算符 ..

public int getMax(int a, int b) 
{
    int c = a - b;
    int k = (c >> 31) & 0x1;
    int max = a - k * c;
    return max;
}
Run Code Online (Sandbox Code Playgroud)

现在你可以做到

int max=Integer.MIN_VALUE-1; 
while(!stack.empty())
{
    max=getMax(max,stack.pop());
}
Run Code Online (Sandbox Code Playgroud)

  • @LukeW.我不同意.来自[wikipedia](http://en.wikipedia.org/wiki/Iteration#Computing),更广泛的定义:"计算中的迭代是计算机程序中一系列语句的重复." 那覆盖了所有的循环和递归.这就是我认为任务模糊定义的原因. (2认同)

Adr*_*ian 5

这可以在O(1)时间和O(n)存储器中完成.修改push和pop方法(或通过继承使用您自己的扩展标准堆栈)来跟踪另一个堆栈中的当前最大值.

将元素推入堆栈时,将max(currentElem,maxStack.peek())推送到maxStack当您从堆栈中弹出元素时,也会从最大堆栈中弹出当前最大值.

这个解决方案很好地说明了,所以我不会对它进行更多扩展:https://stackoverflow.com/a/3435998/1007845

  • 我认为这一定是正确的答案.禁止"迭代"听起来像O(1)获得最大值的方式的代码,这只能通过特殊的数据结构来完成,而不是通用的`java.util.Stack` (2认同)