【问题标题】:Java ArrayDeque push() seems to add to front/tail of stack [potential bug]Java ArrayDeque push() 似乎添加到堆栈的前/尾 [潜在错误]
【发布时间】:2020-07-08 19:11:10
【问题描述】:

我正在研究 leetcode 问题 84,最大矩形。在测试时,我遇到了这种奇怪的情况,堆栈似乎添加到尾部。我使用打印语句和迭代器对象确认了这一点。

测试用例为:[4,2,0,3,2,5]

数组中倒数第二个元素 2 似乎被推到尾部,正好在 0 之下(它应该被推到顶部。在我的打印语句中,val:x gap:y 出现在一个元素是弹出,当一个元素被推入时出现 x y z,并添加:x 是迭代器打印的内容。整个堆栈在数组的每个增量处迭代。代码在这里。我确定只是发布这样的代码块礼节不好,请随时提出批评。

class Solution {
    public int largestRectangleArea(int[] heights) {
        //use a stack
        //if element is bigger than top of stack, than add element to stack
        //if element is same as top, add element to stack
        //if element is less than top, pop all elements and calculate areas, also keep track of area of new top
        
        Deque<Helper> myStack = new ArrayDeque<Helper>();
        
        if (heights.length == 0 || heights == null) return 0;
        if (heights.length == 1) return heights[0];
        
        int poppedLength = 0;
        int area;
        int maxArea = 0;
        Helper previous = new Helper(heights[0]);
        
        myStack.push(previous);
        
        for (int i = 1; i < heights.length; i++) { //iterate through input array
            Iterator<Helper> myIt = myStack.iterator();
            while (myIt.hasNext()) { //iterate through stack, for testing purposes
                System.out.print(myIt.next().toString());
                System.out.println();
            }
            if (!myStack.isEmpty()) {
                if (heights[i] >= myStack.peek().getValue()) {//if curr element is greater than last, push current element
                    myStack.push(new Helper(heights[i]));
                    System.out.print("added1: "); //testing print statements
                    System.out.println(heights[i]);
                } else {
                    while (heights[i] < myStack.peek().getValue()) { //if current element is less than head of stack, pop elements from stack until current is >= head of stack

                        Helper popped = myStack.pop();
                        poppedLength++;
                        
                        area = (poppedLength + popped.getGapLength()) * popped.getValue();
                        System.out.print(poppedLength + popped.getGapLength()); //print statements for testing
                        System.out.print("  ");
                        System.out.print(popped.getValue());
                        System.out.print("  ");
                        System.out.print(area);
                        System.out.println();
                        if (area > maxArea) maxArea = area; //update max

                        if (myStack.isEmpty()) break;

                        
                    }
                    if (!myStack.isEmpty()) {
                        myStack.peek().setGapLength(poppedLength + myStack.peek().getGapLength());

                    } 
                    
                    myStack.add(new Helper(heights[i], poppedLength)); //push current, THIS IS WHERE THE ERROR IS OCCURING
                    System.out.print("added2: ");
                    System.out.println(heights[i]);
                    
                    poppedLength = 0;
                }
            } else {//if stack is empty for some reason, this actually should never execute
                myStack.push(new Helper(heights[i]));
            }
        }
        
        while (!myStack.isEmpty()) {//remove rest of elements in the stack
            Helper popped = myStack.pop();
            poppedLength++;
            
            area = (poppedLength + popped.getGapLength()) * popped.getValue();
            if (area > maxArea) maxArea = area;
            
            System.out.print(poppedLength + popped.getGapLength());
            System.out.print("  ");
            System.out.print(popped.getValue());
            System.out.print("  ");
            System.out.print(area);
            System.out.println();
            
        }
        
        return maxArea;
    }
    
    class Helper {//the elements of the stack
    
        private int value;
        private int gapLength;

        public Helper(int val) {
            value = val;
            gapLength = 0;
        }
        
        public Helper(int val, int gap) {
            value = val;
            gapLength = gap;
        }

        public int getValue() {
            return value;
        }
        
        public int getGapLength() {
            return gapLength;
        }
        
        public void setGapLength(int length) {
            gapLength = length; 
        }
        
        public String toString() {
            String retStr = "Val: " + Integer.toString(value) + "    Gap:" + Integer.toString(gapLength) + "     ";
            return retStr;
        }
    }
}

【问题讨论】:

  • 我不明白这个问题,但我可以向您保证ArrayDeque 中没有根本错误。您是否故意在标记行中使用add 而不是push
  • 我没有,但它们应该具有相同的功能吧?其他测试用例运行良好
  • @valentinocc 你可以通过阅读文档来验证它:ArrayDeque
  • 哇!实际上就是这样。出于某种原因,似乎存在 add 和 push 做一些不同的事情的情况。这很狂野。当我弄清楚确切的问题是什么时,我会发布答案。令人惊讶的是,它在失败之前通过了大约 50 个案例。 @luk2302

标签: java debugging stack arraydeque


【解决方案1】:

您解决问题的方式(将其分解为多个函数)很好。但是,我们很难调试。

这会通过:

class Solution {
    public static int largestRectangleArea(int[] height) {
        if (height == null || height.length == 0) {
            return 0;
        }

        int[] leftReduce = new int[height.length];
        int[] rightReduce = new int[height.length];
        rightReduce[height.length - 1] = height.length;
        leftReduce[0] = -1;

        for (int i = 1; i < height.length; i++) {
            int p = i - 1;

            while (p >= 0 && height[p] >= height[i]) {
                p = leftReduce[p];
            }

            leftReduce[i] = p;
        }

        for (int i = height.length - 2; i >= 0; i--) {
            int p = i + 1;

            while (p < height.length && height[p] >= height[i]) {
                p = rightReduce[p];
            }

            rightReduce[i] = p;
        }

        int maxArea = 0;

        for (int i = 0; i < height.length; i++) {
            maxArea = Math.max(maxArea, height[i] * (rightReduce[i] - leftReduce[i] - 1));
        }

        return maxArea;
    }
}

就像问题下的cmets一样,我也对这行有点疑惑:

Deque<Helper> myStack = new ArrayDeque<Helper>();

参考文献

  • 有关其他详细信息,您可以查看Discussion Board。有很多公认的解决方案,有各种languages 和解释、高效的算法,以及渐近的time/space 复杂性分析1, 2

既然你在准备interviews

  • 我们希望根据标准和约定编写 bug-freeclean 代码(例如,12@987654334 @、212121111)。

  • 在面试期间实施解决方案的时间非常有限。确保不会因为代码设计复杂化而耗尽时间。

祝你面试顺利! ^_^

【讨论】:

  • 谢谢。我喜欢讨论板的解决方案。我只是想知道我的解决方案出了什么问题。我知道调试需要一段时间
  • 感谢采访资源:)。我正在准备
【解决方案2】:

我无法确切地弄清楚我的错误是什么,但能够通过调用 push() 方法而不是 push() 和 add() 方法来解决问题。我怀疑这些方法依赖于不能互换使用。

【讨论】:

    猜你喜欢
    • 2016-05-03
    • 1970-01-01
    • 2013-04-06
    • 2011-03-27
    • 1970-01-01
    • 2015-06-17
    • 2014-07-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多