以下思路來自代碼隨想錄以及官方題解。
文章目錄
- 232.用棧實現隊列
- 225.用隊列實現棧
- 20.有效的括號
- 1047.刪除字符串中所有相鄰重復項
- 150.逆波蘭表達式求值
- 347.前K個高頻元素
232.用棧實現隊列
請你僅使用兩個棧實現先入先出隊列。隊列應當支持一般隊列支持的所有操作(push、pop、peek、empty):
實現 MyQueue
類:
void push(int x)
將元素 x 推到隊列的末尾int pop()
從隊列的開頭移除并返回元素int peek()
返回隊列開頭的元素boolean empty()
如果隊列為空,返回true
;否則,返回false
說明:
- 你只能使用標準的棧操作 —— 也就是只有
push to top
,peek/pop from top
,size
, 和is empty
操作是合法的。 - 你所使用的語言也許不支持棧。你可以使用 list 或者 deque(雙端隊列)來模擬一個棧,只要是標準的棧操作即可。
輸入:
["MyQueue", "push", "push", "peek", "pop", "empty"]
[[], [1], [2], [], [], []]
輸出:
[null, null, null, 1, 1, false]解釋:
MyQueue myQueue = new MyQueue();
myQueue.push(1); // queue is: [1]
myQueue.push(2); // queue is: [1, 2] (leftmost is front of the queue)
myQueue.peek(); // return 1
myQueue.pop(); // return 1, queue is [2]
myQueue.empty(); // return false
用棧來實現隊列,區別就是棧是先進后出,而隊列是先進先出,這時就需要使用兩個棧一個作為出棧一個作為入棧來實現先進先出的特點。
class MyQueue {Deque<Integer> inStack;Deque<Integer> outStack;public MyQueue() {inStack = new ArrayDeque<Integer>();outStack = new ArrayDeque<Integer>();}public void push(int x) {inStack.push(x);}public int pop() {if (outStack.isEmpty()) {in2out();}return outStack.pop();}public int peek() {if (outStack.isEmpty()) {in2out();}return outStack.peek();}public boolean empty() {return inStack.isEmpty() && outStack.isEmpty();}private void in2out() {while (!inStack.isEmpty()) {outStack.push(inStack.pop());}}
}
225.用隊列實現棧
請你僅使用兩個隊列實現一個后入先出(LIFO)的棧,并支持普通棧的全部四種操作(push、top、pop 和 empty)。
實現 MyStack 類:
void push(int x)
將元素 x 壓入棧頂。int pop()
移除并返回棧頂元素。int top()
返回棧頂元素。boolean empty()
如果棧是空的,返回true
;否則,返回false
。
輸入:
["MyStack", "push", "push", "top", "pop", "empty"]
[[], [1], [2], [], [], []]
輸出:
[null, null, null, 2, 2, false]解釋:
MyStack myStack = new MyStack();
myStack.push(1);
myStack.push(2);
myStack.top(); // 返回 2
myStack.pop(); // 返回 2
myStack.empty(); // 返回 False
用隊列實現棧,還是解決如何將先進先出轉變成先進后出,我們可以在push元素的時候進行翻轉。
class MyStack {Queue<Integer> queue;public MyStack() {queue = new LinkedList<Integer>();}public void push(int x) {int n = queue.size();//添加元素queue.offer(x);for(int i=0;i<n;i++){queue.offer(queue.poll());}}public int pop() {//將隊列首元素彈出return queue.poll();}public int top() {return queue.peek();}public boolean empty() {return queue.isEmpty();}
}/*** Your MyStack object will be instantiated and called as such:* MyStack obj = new MyStack();* obj.push(x);* int param_2 = obj.pop();* int param_3 = obj.top();* boolean param_4 = obj.empty();*/
20.有效的括號
給定一個只包括 ‘(’,‘)’,‘{’,‘}’,‘[’,‘]’ 的字符串 s ,判斷字符串是否有效。
有效字符串需滿足:
- 左括號必須用相同類型的右括號閉合。
- 左括號必須以正確的順序閉合。
- 每個右括號都有一個對應的相同類型的左括號。
輸入:s = "()"
輸出:true輸入:s = "()[]{}"
輸出:true輸入:s = "(]"
輸出:false
思路就是先將符號對應的右括號入棧,當遍歷到不是左括號而是右括號時,就拿右括號與棧頂元素比較,如果一致就出棧,繼續。如果不一致就直接結束。
class Solution {public boolean isValid(String s) {if (s.length() % 2 == 1) {return false;}Deque<Character> deque = new LinkedList<>();char ch;for (int i = 0; i < s.length(); i++) {ch = s.charAt(i);if (ch == '{') {deque.push('}');} else if (ch == '[') {deque.push(']');} else if (ch == '(') {deque.push(')');} else if (deque.isEmpty() || deque.peek() != ch) {return false;} else {deque.pop();}}return deque.isEmpty();}
}
1047.刪除字符串中所有相鄰重復項
給出由小寫字母組成的字符串 S
,重復項刪除操作會選擇兩個相鄰且相同的字母,并刪除它們。
在 S 上反復執行重復項刪除操作,直到無法繼續刪除。
在完成所有重復項刪除操作后返回最終的字符串。答案保證唯一。
輸入:"abbaca"
輸出:"ca"
解釋:
例如,在 "abbaca" 中,我們可以刪除 "bb" 由于兩字母相鄰且相同,這是此時唯一可以執行刪除操作的重復項。之后我們得到字符串 "aaca",其中又只有 "aa" 可以執行重復項刪除操作,所以最后的字符串為 "ca"。
class Solution {public String removeDuplicates(String s) {Deque<Character> deque = new LinkedList<>();for(int i=0;i<s.length();i++){if(!deque.isEmpty() && s.charAt(i)==deque.peek()){deque.pop();continue;}deque.push(s.charAt(i));}//棧中字符連接成字符串 caStringBuilder result = new StringBuilder();while (!deque.isEmpty()) {result.insert(0, deque.pop());}return result.toString(); }
}
150.逆波蘭表達式求值
給你一個字符串數組 tokens
,表示一個根據 逆波蘭表示法 表示的算術表達式。
請你計算該表達式。返回一個表示表達式值的整數。
- 有效的算符為 ‘+’、‘-’、‘*’ 和 ‘/’ 。
- 每個操作數(運算對象)都可以是一個整數或者另一個表達式。
- 兩個整數之間的除法總是 向零截斷 。
- 表達式中不含除零運算。
- 輸入是一個根據逆波蘭表示法表示的算術表達式。
- 答案及所有中間計算結果可以用 32 位 整數表示。
輸入:tokens = ["2","1","+","3","*"]
輸出:9
解釋:該算式轉化為常見的中綴算術表達式為:((2 + 1) * 3) = 9輸入:tokens = ["4","13","5","/","+"]
輸出:6
解釋:該算式轉化為常見的中綴算術表達式為:(4 + (13 / 5)) = 6輸入:tokens = ["10","6","9","3","+","-11","*","/","*","17","+","5","+"]
輸出:22
解釋:該算式轉化為常見的中綴算術表達式為:((10 * (6 / ((9 + 3) * -11))) + 17) + 5
= ((10 * (6 / (12 * -11))) + 17) + 5
= ((10 * (6 / -132)) + 17) + 5
= ((10 * 0) + 17) + 5
= (0 + 17) + 5
= 17 + 5
= 22
class Solution {public int evalRPN(String[] tokens) {Deque<Integer> stack = new LinkedList<Integer>();int n = tokens.length;for (int i = 0; i < n; i++) {String token = tokens[i];if (isNumber(token)) {// 如果是數,進棧stack.push(Integer.parseInt(token));} else {// 如果不是數,取數,先是右操作數,后是左操作數int num2 = stack.pop();int num1 = stack.pop();switch (token) {case "+":stack.push(num1 + num2);break;case "-":stack.push(num1 - num2);break;case "*":stack.push(num1 * num2);break;case "/":stack.push(num1 / num2);break;}}}return stack.pop();}public boolean isNumber(String token) {return !("+".equals(token) || "-".equals(token) || "*".equals(token) || "/".equals(token));}}
347.前K個高頻元素
給你一個整數數組 nums
和一個整數 k
,請你返回其中出現頻率前 k 高的元素。你可以按 任意順序 返回答案。
輸入: nums = [1,1,1,2,2,3], k = 2
輸出: [1,2]輸入: nums = [1], k = 1
輸出: [1]
我的解題思路是使用HashMap將所有出現的數字的頻率以鍵值對形式記錄下來,然后再進行操作。
class Solution {public int[] topKFrequent(int[] nums, int k) {HashMap<Integer, Integer> map = new HashMap();for (int i = 0; i < nums.length; i++) {if (map.containsKey(nums[i])) {map.put(nums[i], map.get(nums[i]) + 1);continue;}map.put(nums[i], 0);}// 將map按照value大小進行排序,并取值前k大keyList<Map.Entry<Integer, Integer>> list = new ArrayList<>(map.entrySet());Collections.sort(list, (o1, o2) -> o2.getValue().compareTo(o1.getValue()));int[] result = new int[k];for (int i = 0; i < k; i++) {result[i] = list.get(i).getKey();}return result;}
}