目录
一、150. 逆波兰表达式求值
1.题目描述
评论 (114)
题解(20)New
提交记录
根据逆波兰表示法,求表达式的值。
有效的运算符包括 +, -, *, / 。每个运算对象可以是整数,也可以是另一个逆波兰表达式。
说明:
整数除法只保留整数部分。
给定逆波兰表达式总是有效的。换句话说,表达式总会得出有效数值且不存在除数为 0 的情况。
示例 1:
输入: ["2", "1", "+", "3", "*"]
输出: 9
解释: ((2 + 1) * 3) = 9
示例 2:
输入: ["4", "13", "5", "/", "+"]
输出: 6
解释: (4 + (13 / 5)) = 6
示例 3:
输入: ["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
2.分析:
(1)遇到数字先压栈
(2)一旦碰到符号,则出栈两个数,先出栈为b,后出栈为a(因为题目中“/”规定是前面的数除后面的数,所以我们统一用a/b比较直观),然后对a b进行相应的运算操作。
->这些操作都建立在题设:给定逆波兰表达式总是有效的
(3)将计算结果压栈,作为参数用于下一次计算
(4)最终栈内一定是只剩下一个数,这个数就是结果!
3.代码
class Solution {
public int evalRPN(String[] tokens) {
Stack<Integer> stack = new Stack<>();
int len = tokens.length;
for (int i=0;i<len;i++){
if (tokens[i].equals("+")||tokens[i].equals("-")
||tokens[i].equals("*")||tokens[i].equals("/")){
int b = stack.pop();
int a = stack.pop();
int res = 0;
switch (tokens[i]){
case "+" : {res = a+b;break;}
case "-" : {res = a-b;break;}
case "*" : {res = a*b;break;}
case "/" : {res = a/b;break;}
}
stack.push(res);
}
else {
stack.push(Integer.parseInt(tokens[i]));
}
}
return stack.pop();
}
}
二、71. 简化路径
1.题目描述
评论 (161)
题解(17)New
提交记录
以 Unix 风格给出一个文件的绝对路径,你需要简化它。或者换句话说,将其转换为规范路径。
在 Unix 风格的文件系统中,一个点(.)表示当前目录本身;此外,两个点 (..) 表示将目录切换到上一级(指向父目录);两者都可以是复杂相对路径的组成部分。更多信息请参阅:Linux / Unix中的绝对路径 vs 相对路径
请注意,返回的规范路径必须始终以斜杠 / 开头,并且两个目录名之间必须只有一个斜杠 /。最后一个目录名(如果存在)不能以 / 结尾。此外,规范路径必须是表示绝对路径的最短字符串。
示例 1:
输入:"/home/"
输出:"/home"
解释:注意,最后一个目录名后面没有斜杠。
示例 2:
输入:"/../"
输出:"/"
解释:从根目录向上一级是不可行的,因为根是你可以到达的最高级。
示例 3:
输入:"/home//foo/"
输出:"/home/foo"
解释:在规范路径中,多个连续斜杠需要用一个斜杠替换。
示例 4:
输入:"/a/./b/../../c/"
输出:"/c"
示例 5:
输入:"/a/../../b/../c//.//"
输出:"/c"
示例 6:
输入:"/a//bc/d//././/.."
输出:"/a/b/c"
2.分析
(1)先将字符串拆分成字符串数组,使用String [] s = path.split("/");,以“/”作为拆分符号
->拆分后会产生字符串、空、“.”、“..”四种情况
(2)分类讨论
如果是 空 和 “.” 这两种情况,直接跳过;
如果是 “..” ,出栈一个字符串(即返回上一级的意思)
如果是 字符串 ,直接入栈。
(3)注意题目要求,最终栈内如果没有元素,我们返回“/”
(4)现在栈内顺序是相反的,我们使用StringBuffer 的 方法 str.insert(0,"/"+stack.pop());
出栈、并且存储最终结果!
3.代码
/**
* IMUHERO
* 2019/7/31
*/
package IMUHERO;
import java.util.Stack;
public class Solution71 {
public String simplifyPath(String path) {
String [] s = path.split("/"); //使用“/”分割,会产生字符串、空、“.”、“..”四种情况
int len = s.length;
Stack<String>stack = new Stack<>();
for (int i=0;i<s.length;i++){
if (s[i].equals("")||s[i].equals("."));//不做任何操作,直接i++;
else if (s[i].equals("..")){
if (!stack.isEmpty()){
stack.pop();
}
}
else {
stack.push(s[i]);//如果是字符串,直接压入栈
}
}
if (stack.isEmpty())return "/";
StringBuffer str = new StringBuffer();
while (!stack.isEmpty()){
str.insert(0,"/"+stack.pop());
}
return str.toString();
}
}
三、20.题目要求:
1.题目描述:
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.
二、题目分析:
1.使用栈的数据结构方式
2.先判断是否是‘(’ 、‘[’、'{',是的话依次入栈,不是的话则pop栈内元素,判断是否匹配
3.注意所有输入元素结束后要判断栈内是否还有元素。
三、具体代码:
package IMUHERO;
import java.util.Stack;
class Solution {
public boolean isValid(String s) {
Stack<Character>stack=new Stack<>();
for (int i=0;i<s.length();i++){
char a=s.charAt(i);
if (a=='('||a=='['||a=='{'){
stack.push(a);
}
else {
if (stack.isEmpty())return false;
char topStack=stack.pop();
if (a ==')' &&topStack!='(') return false;
if (a ==']' &&topStack!='[') return false;
if (a =='}' &&topStack!='{') return false;
}
}if (!stack.isEmpty())return false;else return true;
}
}
main函数用于测试功能是否正确:
package IMUHERO;
public class main {
public static void main (String[]args){
Solution s=new Solution();
System.out.println(s.isValid("()"));
System.out.println(s.isValid( "()[]{}"));
System.out.println(s.isValid("(]"));
System.out.println(s.isValid("([)]"));
System.out.println(s.isValid("{[]}"));
}
}
result:
true
true
false
false
true
________________________________________________________
与leetcode上的结果相同:
四、剑指offer(5)
1.题目描述:
用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。
2.题目分析
1.队列是先进先出
2.栈是先进后出
3.push时先放进栈1,pop时先将栈1的元素压入栈2中,这样原本在栈1底下的元素就可以浮在栈2的上顶,这时直接pop栈2即可。
4.特别注意,在栈2的元素还没有完全pop出来时不要把栈1的元素压入栈2,否则先出来的元素又继续在栈2底下存放了。
3.具体代码
import java.util.Stack;
public class Solution {
Stack<Integer> stack1 = new Stack<Integer>();
Stack<Integer> stack2 = new Stack<Integer>();
//int i=0;//i用来记录存入stack中元素的个数
public void push(int node) {
stack1.push(node);
}
public int pop() {
if(!stack2.isEmpty())return stack2.pop();
while(!stack1.isEmpty()){
stack2.push(stack1.pop());
}
return stack2.pop();
}
}
五、剑指offer(三)从尾到头打印链表
输入一个链表,按链表值从尾到头的顺序返回一个ArrayList。
1.利用栈
2.利用ArrayList.add(0,int e),不断添加到第一个位置
3.利用链表递归
1.方法一:栈
import java.util.ArrayList;
import java.util.Stack;
public class Solution {
public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
Stack<Integer> temp = new Stack<>();
ArrayList<Integer> newList = new ArrayList<>();
ListNode t = listNode;
while( t != null ){
temp.push(t.val);
t = t.next;
}
while( !temp.empty() ){
newList.add(temp.pop());
}
return newList;
}
}
2.方法二:ArrayList.add(0,int e)
import java.util.ArrayList;
class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}
public class Solution {
public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
ArrayList<Integer> arr=new ArrayList<>();
ListNode cur=listNode;
while(cur!=null){
arr.add(0,cur.val);
cur=cur.next;
}
return arr;
}
}
3.方法三:递归
import java.util.ArrayList;
public class Solution {
ArrayList<Integer> arr=new ArrayList<>();
public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
print(listNode);
return arr;
}
public void print(ListNode listNode){
if(listNode==null)return;
print(listNode.next);
arr.add(listNode.val);
return;
}
}