From 806e02d3860f7ebb16d510f18f5ce5e187a23a2c Mon Sep 17 00:00:00 2001 From: dingjiawen <745518019@qq.com> Date: Tue, 13 Sep 2022 14:43:06 +0800 Subject: [PATCH] =?UTF-8?q?leecode=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../leecode/stackAndDeque/EvalRPN.java | 123 ++++++++++++++++++ .../leecode/stackAndDeque/IsValid.java | 87 +++++++++++++ .../leecode/stackAndDeque/MyQueue.java | 111 ++++++++++++++++ .../leecode/stackAndDeque/MyQueue1.java | 99 ++++++++++++++ .../leecode/stackAndDeque/MyStack.java | 120 +++++++++++++++++ .../leecode/stackAndDeque/MyStack1.java | 95 ++++++++++++++ 6 files changed, 635 insertions(+) create mode 100644 Leecode/src/main/java/com/markilue/leecode/stackAndDeque/EvalRPN.java create mode 100644 Leecode/src/main/java/com/markilue/leecode/stackAndDeque/IsValid.java create mode 100644 Leecode/src/main/java/com/markilue/leecode/stackAndDeque/MyQueue.java create mode 100644 Leecode/src/main/java/com/markilue/leecode/stackAndDeque/MyQueue1.java create mode 100644 Leecode/src/main/java/com/markilue/leecode/stackAndDeque/MyStack.java create mode 100644 Leecode/src/main/java/com/markilue/leecode/stackAndDeque/MyStack1.java diff --git a/Leecode/src/main/java/com/markilue/leecode/stackAndDeque/EvalRPN.java b/Leecode/src/main/java/com/markilue/leecode/stackAndDeque/EvalRPN.java new file mode 100644 index 0000000..3a176b3 --- /dev/null +++ b/Leecode/src/main/java/com/markilue/leecode/stackAndDeque/EvalRPN.java @@ -0,0 +1,123 @@ +package com.markilue.leecode.stackAndDeque; + +import org.junit.Test; + +import java.util.*; + +/** + * @BelongsProject: Leecode + * @BelongsPackage: com.markilue.leecode.stackAndDeque + * @Author: dingjiawen + * @CreateTime: 2022-09-13 12:06 + * @Description: + * TODO 力扣150题 逆波兰表达式求值: + * 根据 逆波兰表示法,求表达式的值。 + * 有效的算符包括+、-、*、/。每个运算对象可以是整数,也可以是另一个逆波兰表达式。 + * 注意两个整数之间的除法只保留整数部分。 + * 可以保证给定的逆波兰表达式总是有效的。换句话说,表达式总会得出有效数值且不存在除数为 0 的情况。 + * @Version: 1.0 + */ +public class EvalRPN { + + @Test + public void test(){ + String[] tokens = {"2", "1", "+", "3", "*"}; + + System.out.println(evalRPN(tokens)); + } + + @Test + public void test1(){ + String[] tokens = {"4","13","5","/","+"}; + + System.out.println(evalRPN(tokens)); + } + + @Test + public void test2(){ + String[] tokens = {"10","6","9","3","+","-11","*","/","*","17","+","5","+"}; + + System.out.println(evalRPN(tokens)); + } + + @Test + public void test3(){ + String[] tokens = {"2", "1", "+", "3", "*"}; + + System.out.println(evalRPN(tokens)); + } + + /** + * 由于没有括号等操作,考虑使用一个stack解决,遇上运算符,就在往前消两栈,计算出的结果再入栈 + * 由于保证了给定的逆波兰表达式总是有效的,所以不需要额外的判断 + * 速度击败55%,内存击败47% + * @param tokens + * @return + */ + public int evalRPN(String[] tokens) { + + Stack stack = new Stack<>(); + + for (String token : tokens) { + if(!token.equals("+")&&!token.equals("-")&&!token.equals("*")&&!token.equals("/")){ + stack.push(Integer.valueOf(token)); + }else { + int num2=stack.pop(); + int num1=stack.pop(); + if(token.equals("+")){ + stack.push(num1+num2); + }else if(token.equals("-")){ + stack.push(num1-num2); + }else if(token.equals("*")){ + stack.push(num1*num2); + }else if(token.equals("/")){ + stack.push(num1/num2); + } + } + } + return stack.pop(); + + + } + + /** + * 官方给的使用数组模拟栈代码 + * @param tokens + * @return + */ + public int evalRPN1(String[] tokens) { + int n = tokens.length; + int[] stack = new int[(n + 1) / 2]; + int index = -1; + for (int i = 0; i < n; i++) { + String token = tokens[i]; + switch (token) { + case "+": + index--; + stack[index] += stack[index + 1]; + break; + case "-": + index--; + stack[index] -= stack[index + 1]; + break; + case "*": + index--; + stack[index] *= stack[index + 1]; + break; + case "/": + index--; + stack[index] /= stack[index + 1]; + break; + default: + index++; + stack[index] = Integer.parseInt(token); + } + } + return stack[index]; + } + + + + + +} diff --git a/Leecode/src/main/java/com/markilue/leecode/stackAndDeque/IsValid.java b/Leecode/src/main/java/com/markilue/leecode/stackAndDeque/IsValid.java new file mode 100644 index 0000000..bce2c3d --- /dev/null +++ b/Leecode/src/main/java/com/markilue/leecode/stackAndDeque/IsValid.java @@ -0,0 +1,87 @@ +package com.markilue.leecode.stackAndDeque; + +import org.junit.Test; + +import java.util.Stack; + +/** + * @BelongsProject: Leecode + * @BelongsPackage: com.markilue.leecode.stackAndDeque + * @Author: dingjiawen + * @CreateTime: 2022-09-13 11:17 + * @Description: TODO 力扣20题 有效的括号: + * 给定一个只包括 '(',')','{','}','[',']'的字符串 s ,判断字符串是否有效。 + *

+ * 有效字符串需满足: + * 左括号必须用相同类型的右括号闭合。 + * 左括号必须以正确的顺序闭合。 + * 每个右括号都有一个对应的相同类型的左括号。 + * @Version: 1.0 + */ +public class IsValid { + @Test + public void test() { + String s = "{([([])])}"; + System.out.println(isValid(s)); + } + + /** + * 速度击败98%,内存击败35.56% + * + * @param s + * @return + */ + public boolean isValid(String s) { + + if (s.length() % 2 != 0) { + return false; + } + + Stack stack = new Stack<>(); + + for (char c : s.toCharArray()) { + if (c == '{' || c == '(' || c == '[') { + stack.push(c); + } + if (c == ')') { + if (stack.size() == 0 || stack.pop() != '(') { + return false; + } + } + if (c == '}') { + if (stack.size() == 0 || stack.pop() != '{') { + return false; + } + } + if (c == ']') { + if (stack.size() == 0 || stack.pop() != '[') { + return false; + } + } + } + if (!stack.empty()) { + return false; + } + return true; + + } + + /* + 某大佬巧妙思路,不过就是效率不高 + 执行用时:47 ms, 在所有 Java 提交中击败了5.62%的用户 + 内存消耗:41.4 MB, 在所有 Java 提交中击败了5.01%的用户 + + */ + public boolean isValid1(String s) { + while (true) { + int l = s.length(); + s = s.replace("()", ""); + s = s.replace("{}", ""); + s = s.replace("[]", ""); + if (s.length() == l) { + return l == 0; + } + } + } + +} diff --git a/Leecode/src/main/java/com/markilue/leecode/stackAndDeque/MyQueue.java b/Leecode/src/main/java/com/markilue/leecode/stackAndDeque/MyQueue.java new file mode 100644 index 0000000..8a50a73 --- /dev/null +++ b/Leecode/src/main/java/com/markilue/leecode/stackAndDeque/MyQueue.java @@ -0,0 +1,111 @@ +package com.markilue.leecode.stackAndDeque; + +import org.junit.Test; +import org.omg.CORBA.PUBLIC_MEMBER; + +import java.util.Stack; + +/** + * @BelongsProject: Leecode + * @BelongsPackage: com.markilue.leecode.stackAndDeque + * @Author: dingjiawen + * @CreateTime: 2022-09-13 09:17 + * @Description: + * TODO 力扣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(双端队列)来模拟一个栈,只要是标准的栈操作即可。 + * + + * @Version: 1.0 + */ +public class MyQueue { + + public Stack stack1; + public Stack stack2; + + public MyQueue() { + stack1=new Stack<>(); + stack2=new Stack<>(); + + } + + /** + * 本人思路: + * stack1维护一个反向的stack,stack2就维护一个正向的stack + * push时只push进stack1,每调用一次pop就将stack1的值push进stack2 + * 速度击败100%,内存击败50% + * 代码随想录与本思路类似,但是他额peek复用了pop(),即pop()之后再添加回去,另外也不需要每次再pop会stack1,具体见MyQueue1 + * @param x + */ + public void push(int x) { + stack1.push(x); + + } + + public int pop() { + + //放入stack2 + while (!stack1.empty()){ + stack2.push(stack1.pop()); + } + //获取结果 + int result=stack2.pop(); + //放回stack1 + while (!stack2.empty()){ + stack1.push(stack2.pop()); + } + //返回结果 + return result; + + } + + public int peek() { + //放入stack2 + while (!stack1.empty()){ + stack2.push(stack1.pop()); + } + //查看结果结果 + int result=stack2.peek(); + //放回stack1 + while (!stack2.empty()){ + stack1.push(stack2.pop()); + } + return result; + } + + public boolean empty() { + return stack1.empty(); + } + + @Test + public void test(){ + MyQueue myQueue = new MyQueue(); + myQueue.push(1); // queue is: [1] + myQueue.push(2); // queue is: [1, 2] (leftmost is front of the queue) + System.out.println(myQueue.peek());// return 1 + + System.out.println(myQueue.pop());// return 1, queue is [2] + System.out.println(myQueue.empty());// return false + + } + + +} + +/** + * 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(); + */ diff --git a/Leecode/src/main/java/com/markilue/leecode/stackAndDeque/MyQueue1.java b/Leecode/src/main/java/com/markilue/leecode/stackAndDeque/MyQueue1.java new file mode 100644 index 0000000..4240e37 --- /dev/null +++ b/Leecode/src/main/java/com/markilue/leecode/stackAndDeque/MyQueue1.java @@ -0,0 +1,99 @@ +package com.markilue.leecode.stackAndDeque; + +import org.junit.Test; + +import java.util.Stack; + +/** + * @BelongsProject: Leecode + * @BelongsPackage: com.markilue.leecode.stackAndDeque + * @Author: dingjiawen + * @CreateTime: 2022-09-13 09:17 + * @Description: + * TODO 力扣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(双端队列)来模拟一个栈,只要是标准的栈操作即可。 + * + + * @Version: 1.0 + */ +public class MyQueue1 { + + public Stack stack1; + public Stack stack2; + + public MyQueue1() { + stack1=new Stack<>(); + stack2=new Stack<>(); + + } + + /** + * 官方思路: + * 但是他额peek复用了pop(),即pop()之后再添加回去,另外也不需要每次再pop会stack1,具体见MyQueue1 + * 由于充分利用了两个stack,内存利用率大大提高 + * 速度击败100%,内存击败96.07% + * @param x + */ + public void push(int x) { + stack1.push(x); + + } + + public int pop() { + + dumpStack(); + //返回结果 + return stack2.pop(); + + } + + public int peek() { + dumpStack(); + return stack2.peek(); + } + + public boolean empty() { + return stack1.empty()&& stack2.empty(); + } + + private void dumpStack(){ + if(stack2.empty()){ + while (!stack1.empty()){ + stack2.push(stack1.pop()); + } + } + } + + @Test + public void test(){ + MyQueue1 myQueue = new MyQueue1(); + myQueue.push(1); // queue is: [1] + myQueue.push(2); // queue is: [1, 2] (leftmost is front of the queue) + System.out.println(myQueue.peek());// return 1 + + System.out.println(myQueue.pop());// return 1, queue is [2] + System.out.println(myQueue.empty());// return false + + } + + +} + +/** + * 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(); + */ diff --git a/Leecode/src/main/java/com/markilue/leecode/stackAndDeque/MyStack.java b/Leecode/src/main/java/com/markilue/leecode/stackAndDeque/MyStack.java new file mode 100644 index 0000000..e1b86ae --- /dev/null +++ b/Leecode/src/main/java/com/markilue/leecode/stackAndDeque/MyStack.java @@ -0,0 +1,120 @@ +package com.markilue.leecode.stackAndDeque; + +import org.junit.Test; + +import java.util.ArrayDeque; +import java.util.Queue; +import java.util.concurrent.PriorityBlockingQueue; + +/** + * @BelongsProject: Leecode + * @BelongsPackage: com.markilue.leecode.stackAndDeque + * @Author: dingjiawen + * @CreateTime: 2022-09-13 09:59 + * @Description: TODO 力扣225题 用队列实现栈: + * 请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(push、top、pop 和 empty)。 + * 实现 MyStack 类: + * void push(int x) 将元素 x 压入栈顶。 + * int pop() 移除并返回栈顶元素。 + * int top() 返回栈顶元素。 + * boolean empty() 如果栈是空的,返回 true ;否则,返回 false 。 + *

+ *

+ * 注意: + * 你只能使用队列的基本操作 —— 也就是push to back、peek/pop from front、size 和is empty这些操作。 + * 你所使用的语言也许不支持队列。你可以使用 list (列表)或者 deque(双端队列)来模拟一个队列, 只要是标准的队列操作即可。 + * @Version: 1.0 + */ +public class MyStack { + + public Queue queue1; + public Queue queue2; + + + public MyStack() { + queue1 = new ArrayDeque<>(); + queue2 = new ArrayDeque<>(); + } + + /** + * 上述方式是使用两个队列实现栈,事实上还可以使用一个队列实现栈,具体参考MyStack1 + * 速度击败100%,内存击败50% + * @param x + */ + public void push(int x) { + if(queue1.isEmpty()&&queue2.isEmpty()){ + queue1.add(x); + return; + } + + if(queue1.isEmpty()){ + //queue1为空,那么queue2不为空 + queue1.add(x); + while (!queue2.isEmpty()){ + queue1.add(queue2.poll()); + } + }else if(queue2.isEmpty()){ + //queue1为空,那么queue2为空 + queue2.add(x); + while (!queue1.isEmpty()){ + queue2.add(queue1.poll()); + } + } + + + + } + + public int pop() { + if(!queue1.isEmpty()){ + return queue1.poll(); + }else { + return queue2.poll(); + } + + } + + public int top() { + if(!queue1.isEmpty()){ + return queue1.peek(); + }else { + return queue2.peek(); + } + } + + public boolean empty() { + return queue1.isEmpty()&&queue2.isEmpty(); + } + +// public void dumpStack(){ +// if(queue2.isEmpty()){ +// while (!queue1.isEmpty()){ +// queue2.add(queue1.poll()); +// } +// } +// } + + @Test + public void test() { + MyStack obj = new MyStack(); + obj.push(1); + obj.push(2); + obj.push(3); + int param_2 = obj.pop(); + int param_3 = obj.top(); + boolean param_4 = obj.empty(); + + System.out.println(param_2); + System.out.println(param_3); + System.out.println(param_4); + } +} + +/** + * 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(); + */ diff --git a/Leecode/src/main/java/com/markilue/leecode/stackAndDeque/MyStack1.java b/Leecode/src/main/java/com/markilue/leecode/stackAndDeque/MyStack1.java new file mode 100644 index 0000000..6d93e2e --- /dev/null +++ b/Leecode/src/main/java/com/markilue/leecode/stackAndDeque/MyStack1.java @@ -0,0 +1,95 @@ +package com.markilue.leecode.stackAndDeque; + +import org.junit.Test; + +import java.util.ArrayDeque; +import java.util.Queue; + +/** + * @BelongsProject: Leecode + * @BelongsPackage: com.markilue.leecode.stackAndDeque + * @Author: dingjiawen + * @CreateTime: 2022-09-13 09:59 + * @Description: TODO 力扣225题 用队列实现栈: + * 请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(push、top、pop 和 empty)。 + * 实现 MyStack 类: + * void push(int x) 将元素 x 压入栈顶。 + * int pop() 移除并返回栈顶元素。 + * int top() 返回栈顶元素。 + * boolean empty() 如果栈是空的,返回 true ;否则,返回 false 。 + *

+ *

+ * 注意: + * 你只能使用队列的基本操作 —— 也就是push to back、peek/pop from front、size 和is empty这些操作。 + * 你所使用的语言也许不支持队列。你可以使用 list (列表)或者 deque(双端队列)来模拟一个队列, 只要是标准的队列操作即可。 + * @Version: 1.0 + */ +public class MyStack1 { + + public Queue queue1; + + + public MyStack1() { + queue1 = new ArrayDeque<>(); + } + + /** + * 一个队列实现stack,即先把元素加到队列尾部,然后再把头pop出在添加到尾部即可 + * 速度击败100%,内存击败17% + * + * @param x + */ + public void push(int x) { + int size = queue1.size(); + queue1.offer(x); + while (size-- > 0) { + queue1.offer(queue1.poll()); + } + + + } + + public int pop() { + return queue1.poll(); + } + + public int top() { + return queue1.peek(); + } + + public boolean empty() { + return queue1.isEmpty(); + } + +// public void dumpStack(){ +// if(queue2.isEmpty()){ +// while (!queue1.isEmpty()){ +// queue2.add(queue1.poll()); +// } +// } +// } + + @Test + public void test() { + MyStack1 obj = new MyStack1(); + obj.push(1); + obj.push(2); + obj.push(3); + int param_2 = obj.pop(); + int param_3 = obj.top(); + boolean param_4 = obj.empty(); + + System.out.println(param_2); + System.out.println(param_3); + System.out.println(param_4); + } +} + +/** + * 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(); + */