文章目录
- [102. 二叉树的层序遍历 - 力扣(LeetCode) (leetcode-cn.com)](https://leetcode-cn.com/problems/binary-tree-level-order-traversal/)
- [103. 二叉树的锯齿形层序遍历 - 力扣(LeetCode) (leetcode-cn.com)](https://leetcode-cn.com/problems/binary-tree-zigzag-level-order-traversal/)
- [199. 二叉树的右视图 - 力扣(LeetCode) (leetcode-cn.com)](https://leetcode-cn.com/problems/binary-tree-right-side-view/)
- [301. 删除无效的括号 - 力扣(LeetCode) (leetcode-cn.com)](https://leetcode-cn.com/problems/remove-invalid-parentheses/)
- [399. 除法求值 - 力扣(LeetCode) (leetcode-cn.com)](https://leetcode-cn.com/problems/evaluate-division/)
102. 二叉树的层序遍历 - 力扣(LeetCode) (leetcode-cn.com)
- 思路:
- 层序遍历是一个典型的BFS问题。
- 每一层需要进行记录自己该层的所有节点值。
- 本题需要注意的点是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)
- 思路:
- 和上题的思路基本上是一致的。
- 锯齿的话,那么就是让每次添加节点的方向进行一个改变。
- 设置一个标志位flag,如果标志位是true,那么每次在该层添加节点的时候,是每次添加到末尾。否则每次添加到头。
- 与上题区别是这里每层的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)
- 思路:
- 和层序遍历的思路一样,但是只需要右视图(即:从右边看到的节点)。
- 每次在循环的时候,只有当遍历到该层最后一个节点的时候才进行添加。
- 代码:
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)
- 思路:
- 使用set集合进行去重,因为可能会遇见重复的。保证set记录的是不一样的结果。
- 进行一个死循环,再循环中,先对set中的元素进行遍历,如果是满足有效的,那么添加到res中。
- 当对set遍历完成之后,判断res的大小,只要是超过0了,说明有满足的结果,进行返回即可。
- 一旦没有返回,说明没有找到res,那么就创建一个新的set,这一个set的作用是将原字符串进行拆分,拆分为(0,i)和(i+1,length)这两个部分。(如果加上判断的话,执行时间减半)
- 随后将这个新的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; } }
- 大概步骤:
- 在死循环中,第一次是将原数据进行判断,因为肯定是无效的,那么res中是没有答案的,因此,在判断的时候不会执行return;
- 使用一个nextSet就是保存,对第一次数据的不断切割,将set中的每个数据进行分割,分割的标准就是"(“或者”)",每次拼凑好了之后就叫给原set,因为每次判断是对set中的数据进行的判断。
399. 除法求值 - 力扣(LeetCode) (leetcode-cn.com)
这个题太难了,简单的看看吧。
- 思路:
使用邻接节点的方式,那么首先创建结点的表达方式
//邻接节点代表的字符串 public String id; //到达邻接节点所需要的倍数 public double num; public Node(String id, double num){ this.id = id; this.num = num; } } ```
结果集的大小和给定的
queries
大小一致,求出equations
的大小,并同时创建一个HashMap
用来保存每个节点对应的临接结点的信息Map<String, List<Node>> map = new HashMap<>();
,保存每个节点对应其他节点的信息。对给定的
equations
进行循环。
- 每次得到除数(第0个元素)和被除数(第1个元素)。
- 然后如果
map
中没有除数和被除数的key
,那么就进行一个创建,即:map.put(key,new ArrayList<>())
,因为一个节点可能有多个节点对应,所以这里要使用一个列表保存。- 然后分别获取除数和被输出,除数的邻接点就是被除数,被除数的邻接点就是除数,分别取出然后放入节点信息。
创建一个
idx
索引,对queries
进行循环遍历
- 如果map中包含每一个
query
的除数和被除数的信息,那么
- 先从
query
中获取当前的数,以及要求的目的数dest
- 再
new
一个HashMap
为ratios
,这个目的是为了计算对应的乘积。- 先放入
cur
值为1.0
。- 再创建一个
Set
,作用是去重,之后如果有一样的,那么直接跳过。- 再创建一个队列
queue
。先将当前数放入队列中
- 只要队列不为空,并且队列中不包含目的数。
- 先从队列中取出当前数。
- 添加进set中
- 在存储节点信息的map中,获取当前数对应其他节点的信息。
- 只要
set
不包含当前节点的临接结点,那么就进行计算- 给
ratios
放入当前节点的临接结点,以及当前结点在ratios
中的值×临接结点结点的值。- 放入队列中。
- 如果临接结点的
id
等于目标结点的id,那么就跳出。- 在
ratios
中获取目标结点的对应值,否则为-1.0
。- 否则,就出现了没有在
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; } }