leetcode高頻題筆記之棧和隊列

有效的括號

在這裏插入圖片描述
解法:壓棧出棧

public class Solution {
    public boolean isValid(String s) {

        Deque<Character> deque = new LinkedList<>();
        Map<Character, Character> map = new HashMap<>();
        map.put(')', '(');
        map.put(']', '[');
        map.put('}', '{');

        for (char c : s.toCharArray()) {
            if (deque.isEmpty() || deque.peekFirst() != map.get(c)) {
                deque.offerFirst(c);
            } else {
                deque.pollFirst();
            }
        }
        return deque.isEmpty();
    }

    public static void main(String[] args) {
        boolean valid = new Solution().isValid("()[]][");
        System.out.println(valid);
    }
}

最小棧

在這裏插入圖片描述
思路:

  • 運用兩個棧,維護一個值棧和一個最小值棧
  • 入棧時判斷值是否大於最小值棧棧頂,如果大於等於就複製一個棧頂元素到棧頂
  • 如果入棧元素小於最小值棧頂,加入最小值棧
class MinStack {

   Deque<Integer> deque;
    Deque<Integer> minDeque;

    /**
     * initialize your data structure here.
     */
    public MinStack() {
        //值棧
        deque = new LinkedList<>();
        //最小值棧
        minDeque = new LinkedList<>();
    }

    public void push(int x) {
        //入值棧
        deque.offerFirst(x);
        //如果x小於最小值棧頂,就如最小值棧
        if (minDeque.isEmpty() || minDeque.peekFirst() >= x) {
            minDeque.offerFirst(x);
        } else {
            //如果最小值棧數小於x,就拷貝一份最小值在棧頂
            minDeque.offerFirst(minDeque.peekFirst());
        }
    }

    public void pop() {
        deque.pollFirst();
        minDeque.pollFirst();
    }
    public int top() {
        return deque.peekFirst();
    }
    public int getMin() {
        return minDeque.peekFirst();
    }
}

用棧實現隊列

在這裏插入圖片描述

class MyQueue {

    Stack<Integer> in;
    Stack<Integer> out;

    /**
     * Initialize your data structure here.
     */
    public MyQueue() {
        in = new Stack<>();
        out = new Stack<>();
    }

    /**
     * Push element x to the back of queue.
     */
    public void push(int x) {
        in.push(x);
    }

    /**
     * Removes the element from in front of queue and returns that element.
     */
    public int pop() {
        if (out.isEmpty()) {
            while (!in.isEmpty()) {
                out.push(in.pop());
            }
        }
        return out.pop();
    }

    /**
     * Get the front element.
     */
    public int peek() {
        if (out.isEmpty()) {
            while (!in.isEmpty()) {
                out.push(in.pop());
            }
        }
        return out.peek();
    }

    /**
     * Returns whether the queue is empty.
     */
    public boolean empty() {
        return in.isEmpty() && out.isEmpty();
    }
}

用隊列實現棧

在這裏插入圖片描述
思路:維護兩個隊列,保證總有一個隊列是空的

  • push操作,加入到非空的隊列中
  • pop操作,將隊列中size-1的數加入到空的隊列,留下最後一個pop出去
  • top操作,將隊列中size-1的數加入到空的隊列,留下最後一個記錄爲top,再加入到新隊列,返回top
  • empty操作,兩個隊列同時滿足爲空
class MyStack {

    LinkedList<Integer> queue1;
    LinkedList<Integer> queue2;

    /**
     * Initialize your data structure here.
     */
    public MyStack() {
        queue1 = new LinkedList<>();
        queue2 = new LinkedList<>();
    }

    /**
     * Push element x onto stack.
     */
    public void push(int x) {
        if (queue1.isEmpty()) {
            queue2.offer(x);
        } else {
            queue1.offer(x);
        }
    }

    /**
     * Removes the element on top of the stack and returns that element.
     */
    public int pop() {
        if (queue1.isEmpty()) {
            while (queue2.size() > 1) {
                queue1.offer(queue2.poll());
            }
            return queue2.poll();
        } else {
            while (queue1.size() > 1) {
                queue2.offer(queue1.poll());
            }
            return queue1.poll();
        }
    }

    /**
     * Get the top element.
     */
    public int top() {
        int top = 0;
        if (queue1.isEmpty()) {
            while (queue2.size() > 1) {
                queue1.offer(queue2.poll());
            }
            top = queue2.poll();
            queue1.offer(top);
        } else {
            while (queue1.size() > 1) {
                queue2.offer(queue1.poll());
            }
            top = queue1.poll();
            queue2.offer(top);
        }
        return top;
    }

    /**
     * Returns whether the stack is empty.
     */
    public boolean empty() {
        return queue2.isEmpty() && queue1.isEmpty();
    }
}

柱形圖中的最大面積

在這裏插入圖片描述

解法一:暴力枚舉高度

外層循環枚舉每個節點
內層循環枚舉從當前節點開始的後面每個節點,每當枚舉一個節點就計算一次最低高度和最大面積

class Solution {
    public int largestRectangleArea(int[] heights) {
        int maxarea = 0;
        for (int i = 0; i < heights.length; i++) {
            int minheight = Integer.MAX_VALUE;
            for (int j = i; j < heights.length; j++) {
                minheight = Math.min(minheight,heights[j]);
                maxarea = Math.max(maxarea,minheight*(j-i+1));
            }
        }
        return maxarea;

    }
}

解法二:單調棧

官方題解,玩法太高端了,常看看

public class Solution {

    public int largestRectangleArea(int[] heights) {

        int len = heights.length;
        
        if (len == 0) return 0;
        if (len == 1) return heights[0];
        
        int maxSize = 0;
        
        Stack<Integer> stack = new Stack<>();
        stack.push(-1);

        for (int i = 0; i < len; i++) {
            while (stack.peek() != -1 && heights[stack.peek()] >= heights[i]) {
                maxSize = Math.max(maxSize, heights[stack.pop()] * (i - stack.peek() - 1));
            }
            stack.push(i);
        }
        while (stack.peek() != -1) {
            maxSize = Math.max(maxSize, heights[stack.pop()] * (heights.length - stack.peek() - 1));
        }
        
        return maxSize;
    }
}

接雨水

在這裏插入圖片描述
壓棧出棧
總體的原則就是:

  • 當前高度小於等於棧頂高度,入棧,指針後移。

  • 當前高度大於棧頂高度,出棧,計算出當前牆和棧頂的牆之間水的多少,然後計算當前的高度和新棧的高度的關係,重複第 2 步。直到當前牆的高度不大於棧頂高度或者棧空,然後把當前牆入棧,指針後移。

很好的題解

public class Solution {

    public int trap(int[] height) {
        int sum = 0;

        Stack<Integer> stack = new Stack<>();
        int current = 0;

        while (current < height.length) {
            //如果棧不爲空且當前指向的高度大於棧頂高度就一直循環
            while (!stack.empty() && height[current] > height[stack.peek()]) {
                int h = height[stack.pop()];//要出棧的元素

                if (stack.isEmpty()) {//爲空就存不了水
                    break;
                }
                int distance = current - stack.peek() - 1;//兩堵牆之間的距離
                int min = Math.min(height[stack.peek()], height[current]);
                sum += distance * (min - h);
            }
            stack.push(current);//當前牆入棧
            current++;//指針後移

        }
        return sum;
    }
}

每日溫度

在這裏插入圖片描述
運用棧,如果小於棧頂值存入棧,如果大於棧頂的值就將棧頂元素出棧,然後計算距離存入結果數組,反覆出棧直到不滿足大於棧頂元素

public class Solution {
    public int[] dailyTemperatures(int[] T) {
        Stack<Integer> stack = new Stack<>();
        int[] res = new int[T.length];

        for (int i = 0; i < T.length; i++) {
            while (!stack.isEmpty() && T[i] > T[stack.peek()]) {
                Integer pre = stack.pop();
                res[pre] = i-pre;
            }
            stack.push(i);
        }
        return res;
    }
}

下一個更大元素II

和每日溫度類似,只是循環鏈表用兩倍數組長度求模來模擬了
在這裏插入圖片描述

public class Solution {
    public int[] nextGreaterElements(int[] nums) {
        int len = nums.length;
        int[] res = new int[len];

        Arrays.fill(res, -1);

        Stack<Integer> stack = new Stack<>();
        for (int i = 0; i < 2 * len; i++) {
            while (!stack.isEmpty() && nums[i % len] > nums[stack.peek() % len]) {
                Integer pre = stack.pop();
                res[pre % len] = nums[i % len];
            }
            stack.push(i);
        }
        return res;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章