如何在不使用 max() 或对其进行迭代的情况下找到堆栈中的最大整数值?

Posted

技术标签:

【中文标题】如何在不使用 max() 或对其进行迭代的情况下找到堆栈中的最大整数值?【英文标题】:How to Find the Max Integer Value in a Stack without using max() or iterating over it? 【发布时间】:2013-07-24 08:56:10 【问题描述】:

我在一次采访中被问到以下问题:如果你有一个整数堆栈,你如何在不使用 Collections.max 并且不遍历堆栈和比较元素的情况下找到堆栈的最大值。我用下面的代码回答了这个问题,因为我不知道除了使用任何 Collections API 或迭代堆栈并使用比较之外的另一种方法。有什么想法吗?

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());
        
    

【问题讨论】:

疯狂的远射,但我们应该如何理解“比较元素”?将 an 元素与中间变量进行比较是否仍然计数(即遍历堆栈,保持局部最大值并将每个元素与该最大值进行比较) 如果堆栈刚刚交给您并且您不允许查看内容,我看不到执行此操作的方法。也许答案是“定义一个新的 Stack 子类,在其中覆盖 push 操作以更新内部存储的最大值,然后定义 public int max() return this.maxValue; ”? 我建议你先用铅笔和纸用英文写下你需要解决问题的步骤。 @LukeW。只要我的假设认为将单个元素与临时变量进行比较并不构成“比较元素” 我们可以使用 StackSort 吗? xkcd.com/1185(鼠标悬停图片) 【参考方案1】:

编辑:

无需遍历堆栈

实际上并不禁止 all 迭代。相反,这个问题只禁止做简单的事情

for (Integer i : lifo)

因此,此解决方案满足问题的局限性。


只需清空堆栈的副本。从副本中弹出每个元素,同时根据整数检查最大值。

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());

即使你的面试官决定更严格并且不允许更多内置函数(max、min、sort 等),这也会在 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());

最后,这假设与临时变量的比较是可以接受的。如果根本不允许比较,则此解决方案与this method 结合使用即可。

【讨论】:

这不会颠倒堆栈的顺序吗? @LukeW。 Stack&lt;Integer&gt; lifoCopy = lifo.clone(); 不会编译。 @Nima 使用演员表修复。 这不是“迭代堆栈”吗? @BenJackson OP 不打算使用for (Integer i : lifo)。这不是迭代堆栈,而是迭代直到堆栈为空。【参考方案2】:

当你将元素压入堆栈时,更新最大值

void main()
    int max = Integer.min
    lifo.push(1)

同时

   void push(Integer value) 
       //push into stack
       //update max value
   

【讨论】:

可以假设吗?我相信你只会得到一堆整数。【参考方案3】:

您可以将其转换为TreeSet

int myMax = new TreeSet<Integer>(lifo).last();

【讨论】:

为什么要在这里声明一个显式比较器? @arshajii 好的。当我真正有时间时,我会编辑它。如果您愿意,请随意进行编辑。【参考方案4】:

将 Collections.sort 与按降序排序的 Comparator 一起使用,然后从 Stack 中查看顶部元素。

【讨论】:

我认为 OP 想要保留堆栈。 也许答案至少应该提到这一点。【参考方案5】:

改用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());

请注意,自定义 Comparator 会翻转比较,因此 Collections.min() 实际上会返回最大值。

【讨论】:

是的,有趣的设计考虑。 我不确定这是否符合挑战精神,但我喜欢实施:D @HenryKeiter 你可能是对的,但我不能放弃成为聪明人的机会! 如果这不是一个令人讨厌的问题,我会说这是一个令人讨厌的答案......但在上下文中,它是完美的。【参考方案6】:

无需迭代,您就可以进行递归调用。如果这不是家庭作业,那么这样做是不合逻辑的。或者,您也可以在没有迭代和递归的情况下执行此操作。

但是这里有一个快速且简单的方法:

public class StackDemo 
    public static int max = 0; //set this to least, may be negative
    public static Stack lifo = new Stack();
    public static void main(String[] args)        
        pushToStack(new Integer(4));
        pushToStack(new Integer(1));

        if(!lifo.isEmpty())
            Object max = Collections.max(lifo);
            System.out.println("max=" + max);
        
    
    void static int pushToStack(Integer value)
        lifo.push(value);
        if(max<value)
        max = value;
        
        return max;
        


【讨论】:

这应该是递归的吗? 不,不是。它只是一个不使用 max() 的非迭代解决方案;【参考方案7】:

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

if (!lifo.isEmpty()) 
    Stack sc = (Stack) lifo.clone();
    Collections.sort(sc);
    System.out.println("max=" + sc.get(sc.size() - 1));

【讨论】:

我猜这就是答案 对不起,我被要求不要使用 Collections.sort @Smit Collections.sort() 也在后台使用比较。 @c12 你的问题应该反映这一点。 @Juvanis 感谢您的提醒。让我更新答案。和@c12 我同意@LukeW。【参考方案8】:

你可以改用bitwise operator..

public int getMax(int a, int b) 

    int c = a - b;
    int k = (c >> 31) & 0x1;
    int max = a - k * c;
    return max;

现在你可以做

int max=Integer.MIN_VALUE-1; 
while(!stack.empty())

    max=getMax(max,stack.pop());

【讨论】:

有效,但会破坏堆栈。 +1 getMax 功能。如果需要维护堆栈,您需要clone() 或维护另一个堆栈,正如我在回答中讨论的那样。 @LukeW。您可以通过递归避开两个堆栈。看我的回答。我认为 anirudh 的比较和我的递归形成了答案。当然,除非“维护堆栈”是指不弹出/推送它的元素? @linski 没错,但我提供的额外堆栈解决方案不是迭代的,无论您如何定义递归。 @LukeW。我不同意。来自wikipedia 的更广泛定义:“计算中的迭代是计算机程序中语句块的重复。”那就是所有的循环和递归。这就是我认为任务定义模糊的原因。【参考方案9】:

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

当你将元素压入堆栈时,将 max(currentElem, maxStack.peek()) 压入 maxStack 当您从堆栈中弹出元素时,也从您的最大堆栈中弹出当前最大值。

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

【讨论】:

我想这一定是正确的答案。取缔“迭代”听起来像是 O(1) 获取最大值的代码,只能使用特殊的数据结构来完成,而不是通用的 java.util.Stack【参考方案10】:

这段代码:

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()));

输出:

[4, 1, 150, 40, 0, 60, 47, 104]
150
[4, 1, 150, 40, 0, 60, 47, 104]

这是对给定堆栈的递归,查找最大元素并且不更改堆栈顺序。

但是,只有当您 define it like that 时,迭代才不同于递归。此外,为了找到最大值,您必须以某种方式比较所有元素 - 以任何数学形式,使用关系或按位运算符,如 Anirudh showed。恕我直言,定义非常模糊的任务。

【讨论】:

我同意这个问题的含糊之处。有些术语需要在上下文中明确定义,才能解决。【参考方案11】:

是时候跳出框框思考了。使用Wolfram Alpha REST API,并要求它计算以下的结果

"maximum of " + Arrays.deepToString(lifo.toArray())

它将return 150。

【讨论】:

【参考方案12】:
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/
    
 

【讨论】:

【参考方案13】:

这是我的解决方案:

import java.util.Arrays;
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));

        Object lifoArray[] = lifo.toArray();
        Arrays.sort(lifoArray);
        System.out.println(lifoArray[lifoArray.length-1]);
    

Arrays.sort()按升序排列,所以排序后的数组中的最后一个值为最大值。

【讨论】:

【参考方案14】:

1 x - 将元素 x 压入栈中。

2 - 删除栈顶元素。

3 - 打印堆栈中的最大元素。

    import java.io.*;
    import java.util.*;
    import java.text.*;
    import java.math.*;
    import java.util.regex.*;
    public class Solution 
        public static void main(String[] args) 
            Scanner sc = new Scanner(System.in);
            Stack <StackItem> st = new Stack <StackItem> ();
            int n = sc.nextInt();//number of choice
            int choice;
            int max = 0;
            for (int i = 0; i<n; i++) 
               choice = sc.nextInt();
               if (choice == 1) //insert/push an item
                  int newInt = sc.nextInt();
                  if (!st.isEmpty()) 
                      max = st.peek().currentMax;
                   else 
                      max = 0;
                  
                  if (newInt > max) 
                        max = newInt;
                  
                  StackItem item = new StackItem(newInt, max);
                  st.push(item);
                 else if (choice == 2) //pop
                    if (!st.isEmpty()) st.pop();
                 else if (choice == 3) //print the maximum item
                    System.out.println(st.peek().currentMax);
                
            
        
    
    class StackItem 
        int val;
        int currentMax;
        StackItem(int val, int max) 
            this.val = val;
            this.currentMax = max;
        
    

【讨论】:

以上是关于如何在不使用 max() 或对其进行迭代的情况下找到堆栈中的最大整数值?的主要内容,如果未能解决你的问题,请参考以下文章

是否可以在不创建特殊迭代器的情况下每次迭代步进不同的量?

如何在 R/Python 中迭代/循环一个大型(>2GB)JSON 数据集? [复制]

如何在不等待 1 秒的情况下对进程的 CPU 使用情况进行采样

如何在不创建临时对象的情况下迭代嵌套的 TreeMap

如何在不迭代的情况下访问数组中的特定元素?

如何在不复制的情况下从 N 维容器中获取可迭代范围?