rank:1313 / 3582
pass: 3/4
1108. Defanging an IP Address
Given a valid (IPv4) IP address, return a defanged version of that IP address.
A defanged IP address replaces every period “.” with “[.]”.
Example 1:
Input: address = “1.1.1.1”
Output: “1[.]1[.]1[.]1”
Example 2:
Input: address = “255.100.50.0”
Output: “255[.]100[.]50[.]0”
这题没有任何陷阱,直接调用replace就行了
1109. Corporate Flight Bookings
There are n flights, and they are labeled from 1 to n.
We have a list of flight bookings. The i-th booking bookings[i] = [i, j, k] means that we booked k seats from flights labeled i to j inclusive.
Return an array answer of length n, representing the number of seats booked on each flight in order of their label.
Example 1:
Input: bookings = [[1,2,10],[2,3,20],[2,5,25]], n = 5
Output: [10,55,45,25,25]
method 1 暴力解
对于每一个booking,从start到end依次加上k即可,但这道题很容易TLE,前两次都无法pass就是因为做了一些多余的操作浪费时间
public int[] corpFlightBookings(int[][] bookings, int n) {
int[] res = new int[n];
for(int i = 0; i < bookings.length; i++){
int[] booking = bookings[i];
int start = booking[0];
int end = booking[1];
int k = booking[2];
int total = end-start;
int j = 0;
while (j <= total){
int index = j+start-1;
res[index] += k;
j++;
}
}
return res;
}
method 2
method 1 中,对于每个booking,都要遍历start-end之间的数,如果end很大,那么将耗费大量的时间,因此考虑能不能将中间遍历的这些加法操作全部放到最后一次呢?
但是如果放到最后一次,就需要记录该booking中k有多大,并且从什么位置开始,从什么位置结束
因为对中间的所有数所加的k都是一样的,所以我们可以在i处便加k,最后一次遍历时res[i+1] += res[i] 即可,但怎么结束呢,我们可以在res[j-1] -= k就行,减一个k后就抵消了之前加的影响,从而不会影响到j之后的数
public int[] corpFlightBookings(int[][] bookings, int n) {
int[] res = new int[n];
for (int[] b : bookings) {
res[b[0] - 1] += b[2];
if (b[1] < n) res[b[1]] -= b[2];
}
for (int i = 1; i < n; ++i)
res[i] += res[i - 1];
return res;
}
summary:
- 对大量的中间数做同一操作,考虑留到最后统一处理,减少事件复杂度
- 在开始处进行这个操作,在不需要这个操作的位置做一个负操作,而中间的位置只要赋值前一个即可
1110. Delete Nodes And Return Forest
Given the root of a binary tree, each node in the tree has a distinct value.
After deleting all nodes with a value in to_delete, we are left with a forest (a disjoint union of trees).
Return the roots of the trees in the remaining forest. You may return the result in any order.
Example 1:
Input: root = [1,2,3,4,5,6,7], to_delete = [3,5]
Output: [[1,2,null,4],[6],[7]]
method 1
递归处理,每次递归时的判断自己是否为待删节点,然后再判断左右子女是否为待删节点,如果子女为待删节点,直接将其置为null,再判断如果自己parent为null, 且自己又不是待删节点,那么就将自己加入res中
public List<TreeNode> delNodes(TreeNode root, int[] to_delete) {
List<TreeNode> res = new ArrayList<>();
nextIsExist(root, res, null, to_delete);
return res;
}
public boolean nextIsExist(TreeNode root, List<TreeNode> res, TreeNode parent, int[] to_delete) {
if (root == null) return false;
int index = -1;
for (int i = 0; i < to_delete.length; i++) {
if (to_delete[i] == root.val){
index = i;
break;
}
}
TreeNode nextParent = root;
if (index > -1) nextParent = null;
boolean leftExist = nextIsExist(root.left, res, nextParent, to_delete);
if (leftExist) root.left = null;
boolean rightExist = nextIsExist(root.right, res, nextParent, to_delete);
if (rightExist) root.right = null;
if (parent == null && index <= -1)
res.add(root);
if (index > -1) return true;
else return false;
}
method 2
dalao解法。 之前在做的时候就感觉自己的解法很strange,因为我的解法是找到被删除的点,然后从被删除的点切开,分别将被删除节点的父节点那一支和其子节点分别加入。
但我实际看其他人的做法,都是逐次将子节点添加进去,这个算法比较自然一点
- 当该节点是当前树的root节点,并且没有被删,那么就将其加入
- 如果子节点未删,那么就将子节点加入该节点
Set<Integer> to_delete_set;
List<TreeNode> res = new ArrayList<>();
public List<TreeNode> delNodes(TreeNode root, int[] to_delete) {
res = new ArrayList<>();
to_delete_set = new HashSet<>();
for (int i : to_delete)
to_delete_set.add(i);
helper(root, true);
return res;
}
private TreeNode helper(TreeNode node, boolean is_root) {
if (node == null) return null;
boolean deleted = to_delete_set.contains(node.val);
if (is_root && !deleted) res.add(node);
node.left = helper(node.left, deleted);
node.right = helper(node.right, deleted);
return deleted ? null : node;
}
summary:
- 添加节点的方法更自然一点,不要想其他什么特殊操作
1111. Maximum Nesting Depth of Two Valid Parentheses Strings
感觉题目有点奇怪