https://leetcode.cn/problems/serialize-and-deserialize-bst/?envType=daily-question&envId=2023-09-04
提示:
树中节点数范围是 [0, 10^4]
0 <= Node.val <= 10^4
题目数据 保证 输入的树是一棵二叉搜索树。
思路总结:
编码——将二叉搜索树的后序遍历结果保存在列表中,将列表转成字符串。
解码——使用split将列表转成字符串数组,将字符串数组解析到栈中,使用栈重建后序遍历二叉树。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class Codec {
// Encodes a tree to a single string.
public String serialize(TreeNode root) {
List<Integer> list = new ArrayList<>();
postOrder(root, list); // 后序遍历,结果放入list
String str = list.toString();
return str.substring(1, str.length() - 1);
}
// Decodes your encoded data to tree.
public TreeNode deserialize(String data) {
if (data.isEmpty()) return null;
// 这里用", "分割是因为Java的toString方法对列表会生成类似[1, 2, 3]的结果
String[] arr = data.split(", ");
// 将String转成int存入栈中
Deque<Integer> stk = new ArrayDeque<>();
int len = arr.length;
for (int i = 0; i < len; ++i) {
stk.push(Integer.parseInt(arr[i]));
}
return construct(Integer.MIN_VALUE, Integer.MAX_VALUE, stk);
}
// 后序遍历
void postOrder(TreeNode root, List<Integer> ls) {
if (root == null) return;
postOrder(root.left, ls);
postOrder(root.right, ls);
ls.add(root.val);
}
TreeNode construct(int lower, int upper, Deque<Integer> stk) {
if (stk.isEmpty() || stk.peek() < lower || stk.peek() > upper) return null;
int val = stk.pop(); // 取出最后一个节点作为根节点
TreeNode root = new TreeNode(val);
root.right = construct(val, upper, stk); // 重建右子树
root.left = construct(lower, val, stk); // 重建左子树
return root;
}
}
// Your Codec object will be instantiated and called as such:
// Codec ser = new Codec();
// Codec deser = new Codec();
// String tree = ser.serialize(root);
// TreeNode ans = deser.deserialize(tree);
// return ans;
https://leetcode.cn/problems/serialize-and-deserialize-binary-tree/
提示:
树中结点数在范围 [0, 10^4] 内
-1000 <= Node.val <= 1000
https://leetcode.cn/problems/serialize-and-deserialize-binary-tree/solutions/290065/er-cha-shu-de-xu-lie-hua-yu-fan-xu-lie-hua-by-le-2/
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class Codec {
// Encodes a tree to a single string.
public String serialize(TreeNode root) {
return enCode(root, ""); // 存储前序遍历的结果
}
// Decodes your encoded data to tree.
public TreeNode deserialize(String data) {
String[] arr = data.split(",");
List<String> ls = new LinkedList<String>(Arrays.asList(arr));
return deCode(ls);
}
//
public String enCode(TreeNode root, String str) {
if (root == null) {
str += "None,"; // 使用None
} else {
str += str.valueOf(root.val) + ",";
str = enCode(root.left, str);
str = enCode(root.right, str);
}
return str;
}
// 前序遍历重建
public TreeNode deCode(List<String> ls) {
if (ls.get(0).equals("None")) {
ls.remove(0);
return null;
}
TreeNode root = new TreeNode(Integer.valueOf(ls.get(0)));
ls.remove(0);
root.left = deCode(ls);
root.right = deCode(ls);
return root;
}
}
// Your Codec object will be instantiated and called as such:
// Codec ser = new Codec();
// Codec deser = new Codec();
// TreeNode ans = deser.deserialize(ser.serialize(root));
总结一下这种题目的套路——
把二叉树用前序遍历或者后序遍历存成字符串,(如果不是搜索树的话需要用 None 表示空节点)。
重建的时候通过 split 将各个节点变成 列表或者数组的形式存储下来,同样按照前序遍历或者后序遍历重建二叉树即可。
https://leetcode.cn/problems/form-smallest-number-from-two-digit-arrays/description/?envType=daily-question&envId=2023-09-05
提示:
1 <= nums1.length, nums2.length <= 9
1 <= nums1[i], nums2[i] <= 9
每个数组中,元素 互不相同 。
class Solution {
public int minNumber(int[] nums1, int[] nums2) {
int ans = 99, a = 10, b = 10;
Set<Integer> s = new HashSet<>();
for (int num: nums1) {
s.add(num);
a = Math.min(a, num);
}
for (int num: nums2) {
if (s.contains(num)) ans = Math.min(ans, num);
b = Math.min(b, num);
}
// 如果有交集 直接返回
if (ans != 99) return ans;
// 没有交集,返回 a * 10 + b
if (a > b) {
int t = a;
a = b;
b = t;
}
return 10 * a + b;
}
}
class Solution {
public int minNumber(int[] nums1, int[] nums2) {
int mask1 = 0, mask2 = 0;
for (int x: nums1) mask1 |= 1 << x;
for (int x: nums2) mask2 |= 1 << x;
// 检查是否有交集
int m = mask1 & mask2;
if (m > 0) return Integer.numberOfTrailingZeros(m);
// 如果没有交集
int x = Integer.numberOfTrailingZeros(mask1), y = Integer.numberOfTrailingZeros(mask2);
return Math.min(x * 10 + y, y * 10 + x);
}
}
https://leetcode.cn/problems/lowest-common-ancestor-of-deepest-leaves/?envType=daily-question&envId=2023-09-06
提示:
树中的节点数将在 [1, 1000] 的范围内。
0 <= Node.val <= 1000
每个节点的值都是 独一无二 的。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
Queue<TreeNode> q = new LinkedList<>();
Map<TreeNode, TreeNode> m = new HashMap<>();
int d = 0;
public TreeNode lcaDeepestLeaves(TreeNode root) {
dfs(root, 0);
while (q.size() != 1) {
int sz = q.size();
Set<TreeNode> s = new HashSet<>();
for (int i = 0; i < sz; ++i) {
s.add(m.get(q.poll()));
}
for (TreeNode t: s) {
q.offer(t);
}
}
return q.poll();
}
public void dfs(TreeNode root, int t) {
if (root.left == null && root.right == null) {
if (t > d) {
q.clear();
d = t;
}
if (t == d) q.offer(root);
}
else {
if (root.left != null) {
m.put(root.left, root);
dfs(root.left, t + 1);
}
if (root.right != null) {
m.put(root.right, root);
dfs(root.right, t + 1);
}
}
}
}
https://leetcode.cn/problems/lowest-common-ancestor-of-deepest-leaves/solutions/488055/liang-chong-si-lu-yi-chong-qian-xu-bian-li-yi-chon/?envType=daily-question&envId=2023-09-06
class Solution {
TreeNode res = null; // 答案
int pre = 0; // 更新最大深度
public TreeNode lcaDeepestLeaves(TreeNode root) {
dfs(root, 1);
return res;
}
int dfs(TreeNode node, int d) {
if (node == null) return d;
int l = dfs(node.left, d + 1), r = dfs(node.right, d + 1);
if (l == r && l >= pre) {
res = node;
pre = l;
}
return Math.max(l, r);
}
}
https://leetcode.cn/problems/minimum-time-to-repair-cars/?envType=daily-question&envId=2023-09-07
提示:
1 <= ranks.length <= 10^5
1 <= ranks[i] <= 100
1 <= cars <= 10^6
class Solution {
public long repairCars(int[] ranks, int cars) {
Arrays.sort(ranks);
long l = ranks[0], r = (long)ranks[0] * cars * cars;
while (l < r) {
long mid = l + r >> 1;
if (check(mid, ranks, cars)) r = mid;
else l = mid + 1;
}
return l;
}
public boolean check(long k, int[] ranks, int cars) {
for (int r: ranks) {
cars -= Math.floor(Math.sqrt((double)(k / r)));
}
return cars <= 0;
}
}
能力值相同的人,在 t 分钟内修好的车的个数是一样的。
根据数据范围,ranks 中至多有 100 个不同的数字,我们可以统计 ranks 中每个数字的出现次数,这样每次二分至多循环 100 次。
class Solution {
public long repairCars(int[] ranks, int cars) {
int[] cnt = new int[101];
int minR = ranks[0];
for (int r: ranks) {
cnt[r]++;
minR = Math.min(minR, r);
}
long l = 0, r = (long)minR * cars * cars;
while (l < r) {
long mid = l + r >> 1;
if (check(mid, cars, cnt, minR)) r = mid;
else l = mid + 1;
}
return l;
}
public boolean check(long k, int cars, int[] cnt, int minR) {
for (int r = minR; r <= 100; ++r) {
cars -= Math.floor(Math.sqrt(k / r)) * cnt[r];
}
return cars <= 0;
}
}
https://leetcode.cn/problems/calculate-delayed-arrival-time/?envType=daily-question&envId=2023-09-08
提示:
1 <= arrivaltime < 24
1 <= delayedTime <= 24
class Solution {
public int findDelayedArrivalTime(int arrivalTime, int delayedTime) {
return (arrivalTime + delayedTime) % 24;
}
}
https://leetcode.cn/problems/course-schedule/?envType=daily-question&envId=2023-09-09
提示:
1 <= numCourses <= 2000
0 <= prerequisites.length <= 5000
prerequisites[i].length == 2
0 <= ai, bi < numCourses
prerequisites[i] 中的所有课程对 互不相同
class Solution {
public boolean canFinish(int numCourses, int[][] prerequisites) {
List<Integer>[] g = new ArrayList[numCourses];
Arrays.setAll(g, e -> new ArrayList<>());
int[] in = new int[numCourses];
for (int[] p: prerequisites) {
g[p[0]].add(p[1]);
in[p[1]]++;
}
int cnt = numCourses;
Queue<Integer> q = new LinkedList<>();
for (int i = 0; i < numCourses; ++i) {
if (in[i] == 0) {
q.offer(i);
cnt--;
}
}
while (!q.isEmpty()) {
int cur = q.poll();
for (int nt: g[cur]) {
if (--in[nt] == 0) {
q.offer(nt);
cnt--;
}
}
}
return cnt == 0;
}
}
class Solution {
List<Integer>[] g;
boolean[] st;
int[] in;
int sum = 0;
public boolean canFinish(int numCourses, int[][] prerequisites) {
g = new ArrayList[numCourses];
Arrays.setAll(g, e -> new ArrayList<Integer>());
in = new int[numCourses];
st = new boolean[numCourses];
for (int[] prerequisity: prerequisites) {
g[prerequisity[0]].add(prerequisity[1]);
in[prerequisity[1]]++;
}
for (int i = 0; i < numCourses; ++i) {
if (in[i] == 0) {
dfs(i);
}
}
return sum == numCourses;
}
public void dfs(int x) {
if (st[x]) return;
++sum;
st[x] = true;
for (int y: g[x]) {
if (--in[y] == 0) {
dfs(y);
}
}
}
}
https://leetcode.cn/problems/course-schedule-ii/?envType=daily-question&envId=2023-09-10
提示:
1 <= numCourses <= 2000
0 <= prerequisites.length <= numCourses * (numCourses - 1)
prerequisites[i].length == 2
0 <= ai, bi < numCourses
ai != bi
所有[ai, bi] 互不相同
class Solution {
List<Integer>[] g;
List<Integer> ans = new ArrayList();
int[] in;
public int[] findOrder(int numCourses, int[][] prerequisites) {
g = new ArrayList[numCourses];
Arrays.setAll(g, e -> new ArrayList<Integer>());
in = new int[numCourses];
for (int[] prerequisity: prerequisites) {
g[prerequisity[1]].add(prerequisity[0]);
in[prerequisity[0]]++;
}
Queue<Integer> q = new LinkedList<Integer>();
for (int i = 0; i < numCourses; ++i) {
if (in[i] == 0) {
q.offer(i);
ans.add(i);
}
}
while (!q.isEmpty()) {
int x = q.poll();
for (int y: g[x]) {
if (--in[y] == 0) {
ans.add(y);
q.offer(y);
}
}
}
if (ans.size() == numCourses) return ans.stream().mapToInt(Integer::intValue).toArray();
else return new int[]{};
}
}