leetcode-hot100-BFS

102. 二叉树的层序遍历 - 力扣(LeetCode) (leetcode-cn.com)

  • 思路:
  1. 层序遍历是一个典型的BFS问题。
  2. 每一层需要进行记录自己该层的所有节点值。
  3. 本题需要注意的点是Deque接口和List接口在添加的时候,注意接口提供的方法。(这里涉及阻塞队列)
  • 代码:
    class Solution {
        public List<List<Integer>> levelOrder(TreeNode root) {
            Deque<TreeNode> queue = new LinkedList<>();
            List<List<Integer>> res = new LinkedList<>();
            if(root == null){
                return res;
            }
            queue.offer(root);
            while(!queue.isEmpty()){
                int size = queue.size();
                List<Integer> level = new LinkedList<>();//负责记录每层的节点值
                for(int i = 0; i < size; i++){
                    TreeNode node = queue.poll();
                    level.add(node.val);
                    if(node.left != null){
                        queue.offer(node.left);
                    }
                    if(node.right != null){
                        queue.offer(node.right);
                    }
                }
                res.add(level);
            }
            return res;
        }
    }
    

103. 二叉树的锯齿形层序遍历 - 力扣(LeetCode) (leetcode-cn.com)

  • 思路:
  1. 和上题的思路基本上是一致的。
  2. 锯齿的话,那么就是让每次添加节点的方向进行一个改变。
  3. 设置一个标志位flag,如果标志位是true,那么每次在该层添加节点的时候,是每次添加到末尾。否则每次添加到头。
  4. 与上题区别是这里每层的list是使用Deque接口,而不是List接口
  • 代码:
    class Solution {
        public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
            List<List<Integer>> res = new LinkedList<>();
            Deque<TreeNode> queue = new LinkedList<>();
            if(root == null){
                return res;
            }
            boolean flag = true;
            queue.offer(root);
            while(!queue.isEmpty()){
                int size = queue.size();
                Deque<Integer> level = new LinkedList<>();
                for(int i = 0; i < size; i++){
                    TreeNode node = queue.poll();
                    if(flag){
                        level.offerLast(node.val);
                    }else{
                        level.offerFirst(node.val);
                    }
                    if(node.left != null){
                        queue.offer(node.left);
                    }
                    if(node.right != null){
                        queue.offer(node.right);
                    }
                }
                res.add(new LinkedList<>(level));
                flag = !flag;
            }
            return res;
        }
    }
    

199. 二叉树的右视图 - 力扣(LeetCode) (leetcode-cn.com)

  • 思路:
  1. 和层序遍历的思路一样,但是只需要右视图(即:从右边看到的节点)。
  2. 每次在循环的时候,只有当遍历到该层最后一个节点的时候才进行添加。
  • 代码:
    class Solution {
        public List<Integer> rightSideView(TreeNode root) {
            List<Integer> res = new ArrayList<>();
            Deque<TreeNode> queue = new LinkedList<>();
            if(root == null){
                return res;
            }
            queue.offer(root);
            while(!queue.isEmpty()){
                int size = queue.size();
                for(int i = 0; i < size; i++){
                    TreeNode node = queue.poll();
                    if(node.left != null){
                        queue.offer(node.left);
                    }
                    if(node.right != null){
                        queue.offer(node.right);
                    }
                    if(i == size - 1){
                        res.add(node.val);
                    }
                }
            }
            return res;
        }
    }
    

301. 删除无效的括号 - 力扣(LeetCode) (leetcode-cn.com)

  • 思路:
  1. 使用set集合进行去重,因为可能会遇见重复的。保证set记录的是不一样的结果。
  2. 进行一个死循环,再循环中,先对set中的元素进行遍历,如果是满足有效的,那么添加到res中。
  3. 当对set遍历完成之后,判断res的大小,只要是超过0了,说明有满足的结果,进行返回即可。
  4. 一旦没有返回,说明没有找到res,那么就创建一个新的set,这一个set的作用是将原字符串进行拆分,拆分为(0,i)和(i+1,length)这两个部分。(如果加上判断的话,执行时间减半)
  5. 随后将这个新的set复制给set,因为原set的目的就是一个循环判断。
  • 代码:
    class Solution {
        public List<String> removeInvalidParentheses(String s) {
            Set<String> set = new HashSet<>();
            List<String> ans = new ArrayList<>();
            set.add(s);
            while (true) {
                for (String str : set) {
                    if (isRegular(str))
                        ans.add(str);
                }
                if (ans.size() > 0) return ans;
                Set<String> nextSet = new HashSet<>();
                for (String str : set) {
                    for (int i = 0; i < str.length(); i ++) {
                        if (str.charAt(i) == '(' || str.charAt(i) == ')')
                            nextSet.add(str.substring(0, i) + str.substring(i + 1, str.length()));
                    }
                }
                set = nextSet;
            }
        }
        
        public boolean isRegular(String s) {
            char[] ss = s.toCharArray();
            int count = 0;
            for (char c : ss) {
                if (c == '(') count ++;
                else if (c == ')') count --;
                if (count < 0) return false;
            }
            return count == 0;
        }
    }
    
  • 大概步骤:
  1. 在死循环中,第一次是将原数据进行判断,因为肯定是无效的,那么res中是没有答案的,因此,在判断的时候不会执行return;
  2. 使用一个nextSet就是保存,对第一次数据的不断切割,将set中的每个数据进行分割,分割的标准就是"(“或者”)",每次拼凑好了之后就叫给原set,因为每次判断是对set中的数据进行的判断。

399. 除法求值 - 力扣(LeetCode) (leetcode-cn.com)

这个题太难了,简单的看看吧。

  • 思路:
  1. 使用邻接节点的方式,那么首先创建结点的表达方式

        //邻接节点代表的字符串
        public String id;
        //到达邻接节点所需要的倍数
        public double num;
    
        public Node(String id, double num){
            this.id = id;
            this.num = num;
        }    }    ```
    
    
  2. 结果集的大小和给定的queries大小一致,求出equations的大小,并同时创建一个HashMap用来保存每个节点对应的临接结点的信息Map<String, List<Node>> map = new HashMap<>();,保存每个节点对应其他节点的信息。

  3. 对给定的equations进行循环。

    1. 每次得到除数(第0个元素)和被除数(第1个元素)。
    2. 然后如果map中没有除数和被除数的key,那么就进行一个创建,即:map.put(key,new ArrayList<>()),因为一个节点可能有多个节点对应,所以这里要使用一个列表保存。
    3. 然后分别获取除数和被输出,除数的邻接点就是被除数,被除数的邻接点就是除数,分别取出然后放入节点信息。
  4. 创建一个idx索引,对queries进行循环遍历

    1. 如果map中包含每一个query的除数和被除数的信息,那么
      1. 先从query中获取当前的数,以及要求的目的数dest
      2. new一个HashMapratios,这个目的是为了计算对应的乘积。
      3. 先放入cur值为1.0
      4. 再创建一个Set,作用是去重,之后如果有一样的,那么直接跳过。
      5. 再创建一个队列queue。先将当前数放入队列中
        1. 只要队列不为空,并且队列中不包含目的数。
        2. 先从队列中取出当前数。
        3. 添加进set中
        4. 在存储节点信息的map中,获取当前数对应其他节点的信息。
        5. 只要set不包含当前节点的临接结点,那么就进行计算
        6. ratios放入当前节点的临接结点,以及当前结点在ratios中的值×临接结点结点的值。
        7. 放入队列中。
        8. 如果临接结点的id等于目标结点的id,那么就跳出。
      6. ratios中获取目标结点的对应值,否则为-1.0
    2. 否则,就出现了没有在equations出现的字符,这样的话,直接-1即可。
  • 代码:
    class Node {
        //邻接节点代表的字符串
        public String id;
        //到达邻接节点所需要的倍速
        public double num;
    
        public Node(String id, double num){
            this.id = id;
            this.num = num;
        }
    }
    
    class Solution {
        public double[] calcEquation(List<List<String>> equations, double[] values, List<List<String>> queries) {
            double[] res = new double[queries.size()];
            int n = equations.size();
            Map<String, List<Node>> map = new HashMap<>();
            for(int i = 0; i < n; i++){
                String up = equations.get(i).get(0), down = equations.get(i).get(1);
                if(!map.containsKey(up)){
                    map.put(up, new ArrayList<>());
                }
                if(!map.containsKey(down)){
                    map.put(down, new ArrayList<>());
                }
                map.get(up).add(new Node(down, values[i]));
                map.get(down).add(new Node(up, 1.0 / values[i]));
            }
            int cnt = 0;
            for (List<String> query : queries) {
                if (map.containsKey(query.get(0)) && map.containsKey(query.get(1))) {
                    String cur = query.get(0), dest = query.get(1);
                    Map<String, Double> ratios = new HashMap<>();
                    ratios.put(cur, 1.0);
                    Set<String> set = new HashSet<>();
    
                    Queue<String> queue = new LinkedList<>();
                    queue.add(cur);
                    while (!queue.isEmpty() && !queue.contains(dest)) {
                        String u = queue.remove();
                        set.add(u);
                        for (Node node : map.get(u)) {
                            if (!set.contains(node.id)) {
                                ratios.put(node.id, ratios.get(u) * node.num);
                                queue.add(node.id);
                                if (node.id.equals(dest)) {
                                    break;
                                }
                            }
                        }
                    }
                    res[cnt++] = ratios.getOrDefault(dest, -1.0);
                } else {
                    res[cnt++] = -1.0;
                }
            }
            return res;
        }
    }
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值