20 有效的括号
题目描述:
给定一个只包括 '('
,')'
,'{'
,'}'
,'['
,']'
的字符串 s
,判断字符串是否有效。
有效字符串需满足:
- 左括号必须用相同类型的右括号闭合。
- 左括号必须以正确的顺序闭合。
- 每个右括号都有一个对应的相同类型的左括号。
解题思路:
遍历字符串,每遇到左括号,就往栈里丢一个对应的右括号,每遇到右括号,就开始判断——栈顶的元素是不是就是来的这个右括号。只有ch==deque.peek()才是正确的。如果栈为空或者元素不对,都要返回false。最后看栈是不是空,空了就正好。
Java小知识:
1.
Deque是双端队列,是个
接口,其实现类有ArrayDeque
和LinkedList。
2. 泛型参数使用
Character(包装类)
而不是char。
3. 对一个空的
Deque
进行peek
操作时,返回null,null不能与字符直接比较是否相等,会报错。
力扣代码:
class Solution {
public boolean isValid(String s) {
Deque<Character> deque = new LinkedList<>();
char[] t = s.toCharArray();
for(char c:t){
//如果c是左括号,则对应的右括号入栈
if(c == '('){
deque.push(')');
}else if(c == '['){
deque.push(']');
}else if(c == '{'){
deque.push('}');
}
//如果c是右括号,则判断栈顶是否与c相同。如果栈空了,说明没有对应的左括号
else if(deque.isEmpty() || deque.peek() != c){
return false;
}
else{
deque.pop();
}
}
return deque.isEmpty();
}
}
1047 删除字符串中的所有相邻重复项
题目描述:
给出由小写字母组成的字符串 S
,重复项删除操作会选择两个相邻且相同的字母,并删除它们。
在 S 上反复执行重复项删除操作,直到无法继续删除。
在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。
解题思路:
有点像祖马,用栈解决。每进栈一个元素,看栈顶是不是一样的元素。
Java小知识:
ArrayDeque会比LinkedList在除了删除元素这一点外会快一点。
力扣代码:
class Solution {
public String removeDuplicates(String s) {
ArrayDeque<Character> arrayDeque = new ArrayDeque<>();
char[] t = s.toCharArray();
for(char c:t){
if(!arrayDeque.isEmpty() && arrayDeque.peek() == c){
arrayDeque.pop();
}else {
arrayDeque.push(c);
}
}
String res = "";
while (!arrayDeque.isEmpty()){
res = arrayDeque.pop() + res;
}
return res;
}
}
150 逆波兰表达式求值
题目描述:
给你一个字符串数组 tokens
,表示一个根据 逆波兰表示法 表示的算术表达式。
请你计算该表达式。返回一个表示表达式值的整数。
注意:
- 有效的算符为
'+'
、'-'
、'*'
和'/'
。 - 每个操作数(运算对象)都可以是一个整数或者另一个表达式。
- 两个整数之间的除法总是 向零截断 。
- 表达式中不含除零运算。
- 输入是一个根据逆波兰表示法表示的算术表达式。
- 答案及所有中间计算结果可以用 32 位 整数表示。
解题思路:
用栈,遍历字符串,遇到数字就入栈,遇到运算符就弹出2个数字做运算。
Java小知识:
使用
==
运算符:
s == "+"
是使用==
运算符来比较两个字符串对象的引用是否相同,而不是比较字符串的内容。- 如果
s
是一个指向字符串"+"
的引用,而这个字符串恰好是由字符串常量池中的同一个对象表示的,那么s == "+"
的结果为true
。但是,如果s
指向的是内容相同但不是同一个对象的字符串(比如,通过new String("+")
创建的),即使它们的内容相同,s == "+"
的比较结果也会是false
。- 因此,
==
更多用于比较引用类型的变量是否指向堆内存中的同一个对象。使用
.equals()
方法:
"+".equals(s)
是使用String
类的equals()
方法来比较两个字符串的内容是否相等。- 这个方法会逐个字符地比较两个字符串,只有当两个字符串的长度相等且每个对应位置上的字符都相等时,
equals()
方法才返回true
。equals()
方法是比较字符串内容的首选方式,因为它不关心两个字符串对象是否是同一个对象,只关心它们的内容是否相同。
要注意的点:
1. 判断s是否为运算符,不能用s == "+",要用"+".equals(s)。
2. 减法和除法的时候,出栈两个数字,注意运算顺序。
力扣代码:
class Solution {
public int evalRPN(String[] tokens) {
ArrayDeque<Integer> arrayDeque = new ArrayDeque<>();
int tmp = 0;//用于暂存单次运算结果
for (String s:tokens){
if("+".equals(s)){
int tmp1 = arrayDeque.pop();
int tmp2 = arrayDeque.pop();
tmp = tmp1 + tmp2;
arrayDeque.push(tmp);
}
else if("-".equals(s)){
int tmp1 = arrayDeque.pop();
int tmp2 = arrayDeque.pop();
tmp = tmp2 - tmp1;
arrayDeque.push(tmp);
}
else if("*".equals(s)){
int tmp1 = arrayDeque.pop();
int tmp2 = arrayDeque.pop();
tmp = tmp1 * tmp2;
arrayDeque.push(tmp);
}
else if("/".equals(s)){
int tmp1 = arrayDeque.pop();
int tmp2 = arrayDeque.pop();
tmp = tmp2 / tmp1;
arrayDeque.push(tmp);
}
else{
arrayDeque.push(Integer.parseInt(s));
}
}
return arrayDeque.pop();
}
}
347 前K个高频元素
题目描述:
给你一个整数数组 nums
和一个整数 k
,请你返回其中出现频率前 k
高的元素。你可以按 任意顺序 返回答案。
解题思路:
其实是可以用优先队列(小顶堆),找前k大的用小顶堆。你维护一个大小为k的小顶堆,遍历nums的时候每次跟堆顶最小的比,如果比堆顶还小,就不进堆;如果比堆顶大,就弹出堆顶,当前元素进堆。
我没用这个,懒病犯了直接用Map。
遍历nums,整理出一个map,key为数字,value为这些数字出现的次数。然后使用Java的ArrayList
和Collections.sort
方法,结合Lambda表达式,对一个Map
的entrySet
根据其值(value
)进行降序排序。
Java小知识:
Collections.sort(list, (a, b) -> { return b.getValue() - a.getValue(); });
这行代码对列表进行排序。使用了一个Lambda表达式作为比较器(
Comparator
),指明了排序的逻辑:根据Map.Entry
的value
进行降序排序。这里,a
和b
是列表中的两个元素(即两个Map.Entry
对象),Lambda表达式计算它们的value
之差。如果b
的值大于a
的值,则返回正值,意味着b
应该排在a
前面,实现降序排序。// 对map根据 value 进行排序 ArrayList<Map.Entry<Integer, Integer>> list = new ArrayList(map.entrySet()); Collections.sort(list, (a, b) -> { return b.getValue() - a.getValue(); });
力扣代码:
class Solution {
public int[] topKFrequent(int[] nums, int k) {
Map<Integer,Integer> map = new HashMap<>();
int[] res = new int[k];
for (int i:nums){
map.put(i,map.getOrDefault(i,0)+1);
}
List<Map.Entry<Integer, Integer>> list = new ArrayList<>(map.entrySet());
Collections.sort(list,(a,b)->{
return b.getValue() - a.getValue();//b-a是降序
});
for (int i=0;i<k;i++){
res[i] = list.get(i).getKey();
}
return res;
}
}