力扣刷题记录(Java)按代码随想录顺序——栈和队列篇

20 有效的括号

. - 力扣(LeetCode)

题目描述:

给定一个只包括 '('')''{''}''['']' 的字符串 s ,判断字符串是否有效。

有效字符串需满足:

  1. 左括号必须用相同类型的右括号闭合。
  2. 左括号必须以正确的顺序闭合。
  3. 每个右括号都有一个对应的相同类型的左括号。

解题思路:

遍历字符串,每遇到左括号,就往栈里丢一个对应的右括号,每遇到右括号,就开始判断——栈顶的元素是不是就是来的这个右括号。只有ch==deque.peek()才是正确的。如果栈为空或者元素不对,都要返回false。最后看栈是不是空,空了就正好。

Java小知识:

1. Deque是双端队列,是个接口,其实现类有ArrayDequeLinkedList。

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 删除字符串中的所有相邻重复项

. - 力扣(LeetCode)

题目描述:

给出由小写字母组成的字符串 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 逆波兰表达式求值

. - 力扣(LeetCode)

题目描述:

给你一个字符串数组 tokens ,表示一个根据 逆波兰表示法 表示的算术表达式。

请你计算该表达式。返回一个表示表达式值的整数。

注意:

  • 有效的算符为 '+''-''*' 和 '/' 。
  • 每个操作数(运算对象)都可以是一个整数或者另一个表达式。
  • 两个整数之间的除法总是 向零截断 。
  • 表达式中不含除零运算。
  • 输入是一个根据逆波兰表示法表示的算术表达式。
  • 答案及所有中间计算结果可以用 32 位 整数表示。

解题思路:

用栈,遍历字符串,遇到数字就入栈,遇到运算符就弹出2个数字做运算。

Java小知识:

  1. 使用 == 运算符:

    • s == "+" 是使用 == 运算符来比较两个字符串对象的引用是否相同,而不是比较字符串的内容。
    • 如果 s 是一个指向字符串 "+" 的引用,而这个字符串恰好是由字符串常量池中的同一个对象表示的,那么 s == "+" 的结果为 true。但是,如果 s 指向的是内容相同但不是同一个对象的字符串(比如,通过 new String("+") 创建的),即使它们的内容相同,s == "+" 的比较结果也会是 false
    • 因此,== 更多用于比较引用类型的变量是否指向堆内存中的同一个对象。
  2. 使用 .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个高频元素

. - 力扣(LeetCode)

题目描述:

给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。

解题思路:

其实是可以用优先队列(小顶堆),找前k大的用小顶堆。你维护一个大小为k的小顶堆,遍历nums的时候每次跟堆顶最小的比,如果比堆顶还小,就不进堆;如果比堆顶大,就弹出堆顶,当前元素进堆。

我没用这个,懒病犯了直接用Map。

遍历nums,整理出一个map,key为数字,value为这些数字出现的次数。然后使用Java的ArrayListCollections.sort方法,结合Lambda表达式,对一个MapentrySet根据其值(value)进行降序排序。

Java小知识:

  • Collections.sort(list, (a, b) -> { return b.getValue() - a.getValue(); });

    这行代码对列表进行排序。使用了一个Lambda表达式作为比较器(Comparator),指明了排序的逻辑:根据Map.Entryvalue进行降序排序。这里,ab是列表中的两个元素(即两个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;
    }
}

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值