LeetCode刷题笔记-栈和队列

127 阅读2分钟

ArrayDeque和LinkedList类都实现了Deque接口,提供了双端队列。

// 队列:LinkedList类
LinkedList<T> queue = new LinkedList<>(); 
// 入队
add(Object o);
// 出队
remove();

// 栈:ArrayDeque类
Deque<T> stack = new ArrayDeque<>();
// 入栈
addFirst(e);
// 出栈
removeFirst();
// 查看栈顶元素
peekFirst();

20 Valid Parentheses Easy

Given a string containing just the characters '(', ')', '{', '}', '[' and ']', determine if the input string is valid. An input string is valid if:

Open brackets must be closed by the same type of brackets.

Open brackets must be closed in the correct order.

Note that an empty string is also considered valid.

Example 1:

Input: "()"

Output: true

Example 2:

Input: "()[]{}"

Output: true

Example 3:

Input: "(]"

Output: false

Example 4:

Input: "([)]"

Output: false

Example 5:

Input: "{[]}"

Output: true

思路:一次遍历string中的char,如果是左括号就入栈;如果是右括号,检查栈如果为空,证明不能匹配,如果栈不空,弹出top,与当前扫描的括号检查是否匹配。 全部字符都检查完了以后,判断栈是否为空,空则正确都匹配,不空则证明有没匹配的。

class Solution {
    public boolean isValid(String s) {
        Deque<Character> stack = new ArrayDeque<>();
        for(int i=0; i<s.length(); i++) {
            char ch = s.charAt(i);
            if(ch=='(' || ch=='{' || ch=='[') {
                stack.addFirst(ch);
            } else {
                if(stack.size()==0) {
                    return false;
                }
                char top = stack.removeFirst();
                if(!isPaired(top,ch)) {
                    return false;
                }
            }
        }
        return stack.size()==0;
        
    }
    
    private boolean isPaired(char ch1, char ch2) {
        if(ch1=='(' && ch2==')') {
            return true;
        } else if(ch1=='{' && ch2=='}') {
            return true;
        } else if(ch1=='[' && ch2==']') {
            return true;
        } else {
            return false;
        }
    }
}

32 Longest Valid Parentheses Hard

Given a string containing just the characters '(' and ')', find the length of the longest valid (well-formed) parentheses substring.

Example 1:

Input: "(()"

Output: 2

Explanation: The longest valid parentheses substring is "()"

Example 2:

Input: ")()())"

Output: 4

Explanation: The longest valid parentheses substring is "()()"

题意:字符串中只有圆括号'(' ')',求最长匹配括号子串的长度。

思路:需要维护一个合法开始的起点start,用于计算当前合法序列的长度。

需要考虑的例子:()(()

class Solution {
    public int longestValidParentheses(String s) {
        Deque<Integer> stack = new ArrayDeque<>();
        int maxLength = 0;
        int start = 0;
        for(int i=0; i<s.length(); i++) {
            char ch = s.charAt(i);
            if(ch=='(') {
                // 由于本题只有圆括号,所以没有必要将括号入栈
                // 只需要记录入栈的左括号的下标,用于计算合法序列的长度
                stack.addFirst(i);  
            } else {
                if(stack.size()==0) {
                    // 只有)来栈中没有(与之匹配时修改start
                    start = i+1;    
                    continue;
                }
                stack.removeFirst();
                if(stack.size()==0) {
                    maxLength=Math.max(i-start+1, maxLength);
                } else {
                    maxLength=Math.max(i-stack.peek(),maxLength);
                }
                
            }
        }
        return maxLength;
    }
}

84 Largest Rectangle in Histogram Hard

Given n non-negative integers representing the histogram's bar height where the width of each bar is 1, find the area of largest rectangle in the histogram.

Above is a histogram where width of each bar is 1, given height = [2,1,5,6,2,3].

The largest rectangle is shown in the shaded area, which has area = 10 unit.

Example:

Input: [2,1,5,6,2,3]

Output: 10

暴力方法:遍历所有[i, j],并在过程中找出中间最矮的bar,得出从i到j的矩形面积。O(n2)O(n^2),超时。

优雅的方法:用栈 (附图解)

class Solution {
    public int largestRectangleArea(int[] heights) {
        int maxArea = 0;
        int[] h = new int[heights.length+1];
        h = Arrays.copyOf(heights, heights.length+1);
        Deque<Integer> stack = new ArrayDeque<>();
        int i=0;
        while(i<h.length) {
            if(stack.size()==0 || h[i]>=h[stack.peekFirst()]) {
                // 只有入栈后i向后移动
                stack.addFirst(i++);    
            } else {
                int bar = h[stack.removeFirst()];
                maxArea = Math.max(maxArea, stack.size()==0 ? bar*i : bar*(i-stack.peekFirst()-1));
            }
        }
        return maxArea;
    }
}

71 Simplify Path Medium

Given an absolute path for a file (Unix-style), simplify it.

For example,

path = "/home/", => "/home"

path = "/a/./b/../../c/", => "/c"

Corner Cases:

Did you consider the case where path = "/../"?

In this case, you should return "/".

Another corner case is the path might contain multiple slashes '/' together, such as "/home//foo/".

In this case, you should ignore redundant slashes and return "/home/foo".

题意:Linux下的文件目录 . 代表此层目录,.. 代表上一层目录。3个及以上的点照搬。

思路:使用双向队列

class Solution {
    public String simplifyPath(String path) {
        Deque<String> stack = new ArrayDeque<>();
        // 先取/分隔出的内容放入数组
        String[] strings = path.split("/");     
        for(String str:strings) {
            if(str.equals(".") || str.equals("")) {
                continue;
            } else if(str.equals("..")) {
                if(stack.size()!=0) {
                    stack.removeLast();
                }                
            } else {
                stack.addLast(str);
            }
        }
        if(stack.size()==0) {
            return "/";
        }
        StringBuilder builder = new StringBuilder();
        while(stack.size()!=0) {
            builder.append("/"+stack.removeFirst());
        }
        return builder.toString();      
    }
}