1. 程式人生 > >棧相關演算法

棧相關演算法

給定一個只包括 '('')''{''}''['']' 的字串,判斷字串是否有效。

有效字串需滿足:

  1. 左括號必須用相同型別的右括號閉合。
  2. 左括號必須以正確的順序閉合。

注意空字串可被認為是有效字串。

class Solution {
    public boolean isValid(String s) {
        if (s == null || s.length() == 0) {
            return true;
        }
        final char[] charArray = s.toCharArray();
        final Stack<Character> stack = new Stack<Character>();
        for (char c : charArray) {
            if (c == '(' || c == '{' || c == '[') {
                stack.add(c);
            } else if (c == ')' || c == '}' || c == ']') {
                if (stack.isEmpty()) {
                    return false;
                }
                if (c == ')' && stack.peek() == '(') {
                    stack.pop();
                } else if (c == '}' && stack.peek() == '{') {
                    stack.pop();
                } else if (c == ']' && stack.peek() == '[') {
                    stack.pop();
                } else {
                    return false;
                }
            }
        }
        return stack.isEmpty();
    }
}

設計一個支援 push,pop,top 操作,並能在常數時間內檢索到最小元素的棧。

  • push(x) -- 將元素 x 推入棧中。
  • pop() -- 刪除棧頂的元素。
  • top() -- 獲取棧頂元素。
  • getMin() -- 檢索棧中的最小元素。

示例:

MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.getMin();   --> 返回 -3.
minStack.pop();
minStack.top();      --> 返回 0.
minStack.getMin();   --> 返回 -2.
class MinStack {

    /** initialize your data structure here. */
    Stack<Integer> stack;
    Stack<Integer> minStack;
    /** initialize your data structure here. */
    public MinStack() {
        stack = new Stack<Integer>();
        minStack = new Stack<Integer>();
    }
    
    public void push(int x) {
        if (minStack.isEmpty() || getMin() > x) {
            minStack.push(x);
        } else {
            minStack.push(getMin());
        }
        stack.push(x);
    }
    
    public void pop() {
        if (!stack.isEmpty()) {
            stack.pop();
            minStack.pop();
        }
    }
    
    public int top() {
        return stack.peek();
    }
    
    public int getMin() {
        return minStack.peek();
}
}

/**
 * Your MinStack object will be instantiated and called as such:
 * MinStack obj = new MinStack();
 * obj.push(x);
 * obj.pop();
 * int param_3 = obj.top();
 * int param_4 = obj.getMin();
 */

實現一個基本的計算器來計算一個簡單的字串表示式的值。

字串表示式可以包含左括號 ( ,右括號 ),加號 + ,減號 -非負整數和空格  

示例 1:

輸入: "1 + 1"
輸出: 2

示例 2:

輸入: " 2-1 + 2 "
輸出: 3

示例 3:

輸入: "(1+(4+5+2)-3)+(6+8)"
輸出: 23

說明:

  • 你可以假設所給定的表示式都是有效的。
  • 不要使用內建的庫函式 eval
public class Solution {
    public int calculate(String s) {
        if(s == null || s.length() == 0)
            return 0;
        s = "(" + s + ")";
        Stack<Character> cstack = new Stack<Character>();
        Stack<Integer> istack = new Stack<Integer>();
        
        boolean isNum = false;
        int sum = 0;
        
        for(int i = 0 ; i < s.length() ; i++){
            if(s.charAt(i) == ' ')
                continue;
            if(Character.isDigit(s.charAt(i))){
                sum = sum *10 + s.charAt(i) - '0';
                isNum = true;
                continue;
            }else if(isNum){  //考慮到會有 (( 連續的非數字情況 只需壓入一次數字
                istack.push(sum);
                sum = 0;
                isNum = false;
            }
            
            if(s.charAt(i) == '+' || s.charAt(i) == '-' || s.charAt(i) == '('){
                cstack.push(s.charAt(i));
            }else if(s.charAt(i) == ')'){
                int temp = 0;  // 每一次括號裡的值
                while(cstack.peek() != '('){  //直到可以匹配的左括號
                    int a = istack.pop();
                    int c = cstack.pop();
                    if(c == '+'){
                        temp += a;
                    }else if(c == '-'){
                        temp -= a;
                    }
                }
                temp += istack.pop(); // 加上左括號後面的數字
                istack.push(temp);
                cstack.pop();
            }
        }
        
        return istack.pop();
    }
}

使用棧實現佇列的下列操作:

  • push(x) -- 將一個元素放入佇列的尾部。
  • pop() -- 從佇列首部移除元素。
  • peek() -- 返回佇列首部的元素。
  • empty() -- 返回佇列是否為空。

示例:

MyQueue queue = new MyQueue();

queue.push(1);
queue.push(2);  
queue.peek();  // 返回 1
queue.pop();   // 返回 1
queue.empty(); // 返回 false

說明:

  • 你只能使用標準的棧操作 -- 也就是隻有 push to toppeek/pop from topsize, 和 is empty 操作是合法的。
  • 你所使用的語言也許不支援棧。你可以使用 list 或者 deque(雙端佇列)來模擬一個棧,只要是標準的棧操作即可。
  • 假設所有操作都是有效的 (例如,一個空的佇列不會呼叫 pop 或者 peek 操作)。
class MyQueue {

    Stack<Integer> stack;
    Stack<Integer> reverseStack;
    /** Initialize your data structure here. */
    public MyQueue() {
        stack = new Stack<>();
        reverseStack = new Stack<>();
    }
    
    /** Push element x to the back of queue. */
    public void push(int x) {
        while (!reverseStack.isEmpty()) {
            stack.push(pop());
        }
        stack.push(x);

        // Pure back
        while (!stack.isEmpty()) {
            reverseStack.push(stack.pop());
        }
    }
    
    /** Removes the element from in front of queue and returns that element. */
    public int pop() {
        return reverseStack.pop();
    }
    
    /** Get the front element. */
    public int peek() {
        return reverseStack.peek();
    }
    
    /** Returns whether the queue is empty. */
    public boolean empty() {
        return reverseStack.isEmpty();
    }
}

/**
 * Your MyQueue object will be instantiated and called as such:
 * MyQueue obj = new MyQueue();
 * obj.push(x);
 * int param_2 = obj.pop();
 * int param_3 = obj.peek();
 * boolean param_4 = obj.empty();
 */

 

給定兩個沒有重複元素的陣列 nums1 和 nums2 ,其中nums1 是 nums2 的子集。找到 nums1 中每個元素在 nums2 中的下一個比其大的值。

nums1 中數字 x 的下一個更大元素是指 x 在 nums2 中對應位置的右邊的第一個比 大的元素。如果不存在,對應位置輸出-1。

示例 1:

輸入: nums1 = [4,1,2], nums2 = [1,3,4,2].
輸出: [-1,3,-1]
解釋:
    對於num1中的數字4,你無法在第二個陣列中找到下一個更大的數字,因此輸出 -1。
    對於num1中的數字1,第二個陣列中數字1右邊的下一個較大數字是 3。
    對於num1中的數字2,第二個陣列中沒有下一個更大的數字,因此輸出 -1。

示例 2:

輸入: nums1 = [2,4], nums2 = [1,2,3,4].
輸出: [3,-1]
解釋:
    對於num1中的數字2,第二個陣列中的下一個較大數字是3。
    對於num1中的數字4,第二個陣列中沒有下一個更大的數字,因此輸出 -1。

注意:

  1. nums1nums2中所有元素是唯一的。
  2. nums1nums2 的陣列大小都不超過1000。
class Solution {
    public int[] nextGreaterElement(int[] nums1, int[] nums2) {
        int m = nums1.length, n = nums2.length;
        int[] result = new int[m];
        Map<Integer, Integer> pos = new HashMap<>();
        for (int i = 0; i < n; i++) {
            pos.put(nums2[i], i);
        }
        for (int i = 0; i < m; i++) {
            result[i] = check(nums2, pos.get(nums1[i]), nums1[i]);
        }
        return result;
    }
    
    private int check(int[] nums, int index, int val) {
        for (int i = index; i < nums.length; i++) {
            if (nums[i] > val) return nums[i];
        }
        return -1;
    }
}

 

給定 ST 兩個字串,當它們分別被輸入到空白的文字編輯器後,判斷二者是否相等,並返回結果。 # 代表退格字元。

 

示例 1:

輸入:S = "ab#c", T = "ad#c"
輸出:true
解釋:S 和 T 都會變成 “ac”。

示例 2:

輸入:S = "ab##", T = "c#d#"
輸出:true
解釋:S 和 T 都會變成 “”。

示例 3:

輸入:S = "a##c", T = "#a#c"
輸出:true
解釋:S 和 T 都會變成 “c”。

示例 4:

輸入:S = "a#c", T = "b"
輸出:false
解釋:S 會變成 “c”,但 T 仍然是 “b”。

提示:

  1. 1 <= S.length <= 200
  2. 1 <= T.length <= 200
  3. ST 只含有小寫字母以及字元 '#'
class Solution {
    public boolean backspaceCompare(String S, String T) {
        if (S == null || T == null) return false;
        
        return type(S).equals(type(T));
    }
    
    private String type(String s) {
        Stack<Character> stack = new Stack<>();
        for (char c : s.toCharArray()) {
            if (c == '#') {
                if (!stack.isEmpty()) stack.pop();
            } else {
                stack.push(c);
            }
        }
        StringBuffer sb = new StringBuffer();
        while (!stack.isEmpty()) {
            sb.append(stack.pop());
        }
        return sb.toString();
    }
}