三刷
Version #3 Sort start & end at the same time
3.68 %
class Solution {
public int minMeetingRooms(Interval[] intervals) {
if (intervals == null || intervals.length == 0) return 0;
List<int[]> list = new ArrayList<>();
for (Interval interval : intervals) {
list.add(new int[]{interval.start, 1});
list.add(new int[]{interval.end, -1});
}
Collections.sort(list, (a, b) -> {
if (a[0] == b[0]) return a[1] - b[1]; // end happens before start
return a[0] - b[0];
});
int count = 0;
int result = 0;
for (int i = 0; i < list.size(); i++) {
count += list.get(i)[1];
result = Math.max(result, count);
}
return result;
}
}
Version #2
sort start & end separately
用count表示现在有的meeting rooms的数量
如果有meeting结束 可以把后面的放进vacant的room
如果没有结束的meeting 就需要增加rooms的数量
81.05 %
class Solution {
public int minMeetingRooms(Interval[] intervals) {
if (intervals == null || intervals.length == 0) return 0;
int length = intervals.length;
int[] starts = new int[length];
int[] ends = new int[length];
for (int i = 0; i < length; i++) {
starts[i] = intervals[i].start;
ends[i] = intervals[i].end;
}
Arrays.sort(starts);
Arrays.sort(ends);
int count = 0;
int pEnd = 0;
for (int pStart = 0; pStart < length; pStart++) {
if (starts[pStart] < ends[pEnd]) {
count++;
} else {
pEnd++;
}
}
return count;
}
}
Version #1 Naive Sort Intervals Version
重点是breaking tie
看到discuss里面还有用heap和分别sort start&end的方法,懒得看了
49.06 %
class Solution {
class Tuple implements Comparable<Tuple> {
int time;
int isStart; //start -> 1, end -> 0
public Tuple(int time, int isStart) {
this.time = time;
this.isStart = isStart;
}
@Override
public int compareTo(Tuple that) {
if (this.time != that.time) {
return this.time - that.time;
} else {
return this.isStart - that.isStart;
}
}
}
public int minMeetingRooms(Interval[] intervals) {
if (intervals == null || intervals.length == 0) return 0;
List<Tuple> times = new ArrayList<>();
for (Interval i : intervals) {
times.add(new Tuple(i.start, 1));
times.add(new Tuple(i.end, 0));
}
Collections.sort(times);
int max = 0;
int count = 0;
for (Tuple tuple : times) {
if (tuple.isStart == 1) {
count++;
max = Math.max(count, max);
} else {
count--;
}
}
return max;
}
}
Tuesday, September 19, 2017
416. Partition Equal Subset Sum
二刷 07/2022
Version #1 0/1 Knapsack
Time O(N * Sum)
Space O(N * Sum)
Runtime: 26 ms, faster than 91.77% of Java online submissions for Partition Equal Subset Sum.
Memory Usage: 43.5 MB, less than 75.86% of Java online submissions for Partition Equal Subset Sum.
class Solution {
public boolean canPartition(int[] nums) {
int target = 0;
for (int num : nums) {
target += num;
}
if (target % 2 != 0) {
return false;
}
target /= 2;
// dp[i][s] - [0, i) numbers can add up to s
boolean[][] dp = new boolean[nums.length + 1][target + 1];
dp[0][0] = true;
for (int i = 1; i <= nums.length; i++) {
for (int j = target; j >= 0; j--) {
if (dp[i - 1][j] || (j >= nums[i - 1] && dp[i - 1][j - nums[i - 1]])) {
dp[i][j] = true;
}
}
if (dp[i][target]) {
return true;
}
}
return dp[nums.length][target];
}
}
Version #2 HashSet
Time O(N * Sum of all numbers)
Space O(Sum of all numbers)
Runtime: 410 ms, faster than 5.82% of Java online submissions for Partition Equal Subset Sum.
Memory Usage: 117.8 MB, less than 6.46% of Java online submissions for Partition Equal Subset Sum.
class Solution {
public boolean canPartition(int[] nums) {
int target = 0;
for (int num : nums) {
target += num;
}
if (target % 2 != 0) {
return false;
}
target /= 2;
Set<Integer> visited = new HashSet<>();
visited.add(0);
for (int num : nums) {
Set<Integer> newSum = new HashSet<>();
for (int prev : visited) {
if (prev + num == target) {
return true;
}
newSum.add(prev + num);
}
visited.addAll(newSum);
}
return false;
}
}
一刷 06/2022
Version #1 0/1 Knapsack DP
It could be optimized to 1d DP
Time O(N*Sum)
Space O(N*Sum)
Runtime: 51 ms, faster than 61.41% of Java online submissions for Partition Equal Subset Sum.
Memory Usage: 54.3 MB, less than 44.88% of Java online submissions for Partition Equal Subset Sum.
class Solution {
public boolean canPartition(int[] nums) {
int sum = 0;
for (int num : nums) {
sum += num;
}
if (sum % 2 != 0) {
return false;
}
sum /= 2;
// System.out.printf("sum=%d\n", sum);
// The [0, i) numbers can sum up to j
boolean[][] dp = new boolean[nums.length + 1][sum + 1];
// The first 0 number can sum up to 0
dp[0][0] = true;
for (int i = 1; i <= nums.length; i++) {
// the nums[i - 1] item
int num = nums[i - 1];
for (int j = 0; j < sum + 1; j++) {
if (num <= j) {
dp[i][j] = dp[i - 1][j] || dp[i - 1][j - num];
} else {
dp[i][j] = dp[i - 1][j];
}
}
if (dp[i][sum]) {
return true;
}
}
return dp[nums.length][sum];
}
}
297. Serialize and Deserialize Binary Tree
参考 449. Serialize and Deserialize BST
Version #5 Byte Manipulation
这个方法是把Integer直接变成string给改成byte 表示法,可以压缩space
String ->
-2^31 = -2147483648 -> 11 chars
https://www.javamex.com/tutorials/memory/string_memory_usage.shtml
Byte -> 0xFFFFFFFF
4 bytes
No string-integer conversion needed
如果是 int -> byte[] -> char[] 的话,转换回来的时候
如果不
// return (int) ((data[0] & 0xff) << 24)
// | ((data[1] & 0xff) << 16)
// | ((data[2] & 0xff) << 8)
// | (data[3] & 0xff);
就会出错
然而如果直接 int -> char[]就不需要考虑这个问题,因为在int -> char[] 的时候已经
(char)((x >> 24) & 0xff),
(char)((x >> 16) & 0xff),
(char)((x >> 8) & 0xff),
(char)(x & 0xff)
了
99.15 %
public class Codec {
private char NULL_VALUE = '0';
private char NOT_NULL_VALUE = '1';
// Encodes a tree to a single string.
public String serialize(TreeNode root) {
StringBuilder sb = new StringBuilder();
seHelper(root, sb);
return sb.toString();
}
private void seHelper(TreeNode node, StringBuilder sb) {
if (node == null) {
sb.append(NULL_VALUE);
return;
}
char[] array = int2Bytes(node.val);
sb.append(NOT_NULL_VALUE).append(array[0]).append(array[1]).append(array[2]).append(array[3]);
seHelper(node.left, sb);
seHelper(node.right, sb);
}
private char[] int2Bytes(int x) {
return new char[]{
(char)((x >> 24) & 0xff),
(char)((x >> 16) & 0xff),
(char)((x >> 8) & 0xff),
(char)(x & 0xff)
};
}
// Decodes your encoded data to tree.
private int index;
public TreeNode deserialize(String data) {
index = 0;
return deHelper(data.toCharArray());
}
private TreeNode deHelper(char[] data) {
if (data[index++] == NULL_VALUE) {
return null;
}
TreeNode node = new TreeNode(bytes2Int(new char[]{
data[index],
data[index + 1],
data[index + 2],
data[index + 3]
}));
index += 4;
node.left = deHelper(data);
node.right = deHelper(data);
return node;
}
private int bytes2Int(char[] data) {
return (int) (data[0] << 24)
| (data[1] << 16)
| (data[2] << 8)
| data[3];
}
}
Version #3 Iteration with Stack
二刷
看一刷的不知道自己在写什么。。。为什么需要一个boolean来判断是不是left?
Stack 加的时候注意是先左后右
Stack deserialize的时候,都是向左走到底,然后向右跳一个
39.88 %
public class Codec {
// Encodes a tree to a single string.
public String serialize(TreeNode root) {
if (root == null) {
return null;
}
StringBuilder sb = new StringBuilder();
Deque<TreeNode> stack = new LinkedList<>();
stack.addFirst(root);
while (!stack.isEmpty()) {
TreeNode curr = stack.removeFirst();
if (curr == null) {
sb.append("#,");
} else {
sb.append(curr.val + ",");
stack.addFirst(curr.right);
stack.addFirst(curr.left);
}
}
System.out.println(sb.toString());
return sb.toString();
}
// Decodes your encoded data to tree.
public TreeNode deserialize(String data) {
if (data == null || data.length() == 0) {
return null;
}
String[] strs = data.split(",");
Deque<TreeNode> stack = new LinkedList<>();
int pointer = 0;
if (strs.length == 0 || strs[pointer].equals("#")) {
return null;
}
TreeNode root = new TreeNode(Integer.valueOf(strs[0]));
TreeNode curr = root;
stack.addFirst(root);
pointer++;
while (pointer < strs.length) {
while (curr != null) {
stack.addFirst(curr);
curr.left = strs[pointer].equals("#") ? null : new TreeNode(Integer.valueOf(strs[pointer]));
pointer++;
curr = curr.left;
}
curr = stack.removeFirst();
curr.right = strs[pointer].equals("#") ? null : new TreeNode(Integer.valueOf(strs[pointer]));
pointer++;
curr = curr.right;
}
return root;
}
}
一刷
Iteration desirialization 好难啊,写了好久好久好久
stack里面放的是已经连完左节点但是等待右subtree的点
curr代表的是当下等待连左节点的点
如果遇到null
1st -> 证明当前curr的left subtree是null
当前curr已经是Left most node
开始往外pop
2nd -> 在pop round,pop出的点是waiting for its right subtree
此时遇到null 证明当前点的right subtree是NULL
直接继续pop
37.48 %
public class Codec {
private static final String DIVIDER = "/";
private static final String NULL = "null";
// Encodes a tree to a single string.
public String serialize(TreeNode root) {
if (root == null) return null;
StringBuilder sb = new StringBuilder();
Stack<TreeNode> stack = new Stack<>();
TreeNode curr = root;
while (curr != null || !stack.isEmpty()) {
if (curr != null) {
sb.append(curr.val);
sb.append(DIVIDER);
stack.push(curr);
curr = curr.left;
} else {
sb.append(NULL + DIVIDER);
curr = stack.pop();
curr = curr.right;
}
}
sb.deleteCharAt(sb.length() - 1);
return sb.toString();
}
// Decodes your encoded data to tree.
public TreeNode deserialize(String data) {
if (data == null) return null;
String[] strs = data.trim().split(DIVIDER);
int index = 0;
TreeNode root = new TreeNode(Integer.valueOf(strs[index++]));
Stack<TreeNode> stack = new Stack<>();
TreeNode curr = root;
stack.push(curr);
int n = strs.length;
// Nodes in stack -> waiting for their right subtree
// curr -> waiting for its left subtree
while (index < n) {
while (index < n && !strs[index].equals(NULL)) {
curr.left = new TreeNode(Integer.valueOf(strs[index++]));
curr = curr.left;
stack.push(curr);
}
// Top nodes left subtree is null, get the next candidate node
while (index < n && strs[index].equals(NULL)) {
curr = stack.pop();
index++;
}
// strs[index] is not NULL
if (index < n) {
curr.right = new TreeNode(Integer.valueOf(strs[index++]));
curr = curr.right;
stack.push(curr);
}
}
return root;
}
}
Version #4 Recursion DFS
Pre-Order Traversal
注意pointer是一个global变量,每一次recursion的当前层负责给pointer + 1
二刷
94.28 %
public class Codec {
// Encodes a tree to a single string.
public String serialize(TreeNode root) {
StringBuilder sb = new StringBuilder();
seHelper(root, sb);
return sb.toString();
}
private void seHelper(TreeNode node, StringBuilder sb) {
if (node == null) {
sb.append("#,");
return;
}
sb.append(node.val + ",");
seHelper(node.left, sb);
seHelper(node.right, sb);
}
// Decodes your encoded data to tree.
public TreeNode deserialize(String data) {
if (data == null || data.length() == 0) {
return null;
}
String[] strs = data.split(",");
int[] pointer = new int[]{0};
return deHelper(strs, pointer);
}
private TreeNode deHelper(String[] strs, int[] pointer) {
if (strs[pointer[0]].equals("#")) {
pointer[0]++;
return null;
}
TreeNode node = new TreeNode(Integer.valueOf(strs[pointer[0]]));
pointer[0]++;
node.left = deHelper(strs, pointer);
node.right = deHelper(strs, pointer);
return node;
}
}
Version #1 jiuzhang Version BFS with Queue
二刷
49.87 %
public class Codec {
// Encodes a tree to a single string.
public String serialize(TreeNode root) {
StringBuilder sb = new StringBuilder();
Queue<TreeNode> que = new LinkedList<>();
if (root == null) {
return null;
}
que.offer(root);
while (!que.isEmpty()) {
TreeNode curr = que.poll();
if (curr == null) {
sb.append("#,");
} else {
sb.append(curr.val + ",");
que.offer(curr.left);
que.offer(curr.right);
}
}
return sb.toString();
}
// Decodes your encoded data to tree.
public TreeNode deserialize(String data) {
if (data == null || data.length() == 0) {
return null;
}
String[] strs = data.split(",");
Queue<TreeNode> que = new LinkedList<>();
if (strs.length == 0) {
return null;
}
int pointer = 0;
TreeNode root = new TreeNode(Integer.valueOf(strs[pointer++]));
que.offer(root);
while (!que.isEmpty()) {
TreeNode curr = que.poll();
TreeNode left = null;
if (!strs[pointer].equals("#")) {
left = new TreeNode(Integer.valueOf(strs[pointer]));
que.offer(left);
}
pointer++;
curr.left = left;
TreeNode right = null;
if (!strs[pointer].equals("#")) {
right = new TreeNode(Integer.valueOf(strs[pointer]));
que.offer(right);
}
pointer++;
curr.right = right;
}
return root;
}
}
一刷
49.35 %
public class Codec {
// Encodes a tree to a single string.
public String serialize(TreeNode root) {
if (root == null) return "{}";
ArrayList<TreeNode> que = new ArrayList<>();
que.add(root);
TreeNode curr = null;
for (int i = 0; i < que.size(); i++) {
curr = que.get(i);
if (curr == null) continue;
que.add(curr.left);
que.add(curr.right);
}
StringBuilder sb = new StringBuilder();
sb.append("{");
curr = que.get(0);
int index = 1;
sb.append(String.valueOf(curr.val));
while (index < que.size()) {
curr = que.get(index);
index++;
sb.append(",");
if (curr == null) sb.append("#");
else sb.append(String.valueOf(curr.val));
}
sb.append("}");
return sb.toString();
}
// Decodes your encoded data to tree.
public TreeNode deserialize(String data) {
if (data.equals("{}")) {
return null;
}
String[] vals = data.substring(1, data.length() - 1).split(",");
ArrayList<TreeNode> queue = new ArrayList<TreeNode>();
TreeNode root = new TreeNode(Integer.parseInt(vals[0]));
queue.add(root);
int index = 0;
boolean isLeftChild = true;
for (int i = 1; i < vals.length; i++) {
if (!vals[i].equals("#")) {
TreeNode node = new TreeNode(Integer.parseInt(vals[i]));
if (isLeftChild) {
queue.get(index).left = node;
} else {
queue.get(index).right = node;
}
queue.add(node);
}
if (!isLeftChild) {
index++;
}
isLeftChild = !isLeftChild;
}
return root;
}
}
// Your Codec object will be instantiated and called as such:
// Codec codec = new Codec();
// codec.deserialize(codec.serialize(root));
Version #2
57.60 %
自己改进了一下感觉比上个方法简洁一点 就是传统地用queue
上个方法里面用ArrayList作为Queue然后用get(index) 来代替queue.poll()感觉也挺有意思的
注意!string == "#"是不对的 必须string.equals("#");
public class Codec {
// Encodes a tree to a single string.
public String serialize(TreeNode root) {
if (root == null) return "";
StringBuilder sb = new StringBuilder();
Queue<TreeNode> que = new LinkedList<>();
que.add(root);
TreeNode curr = null;
while (!que.isEmpty()) {
curr = que.poll();
if (curr == null) {
sb.append("#,");
continue;
} else {
sb.append(String.valueOf(curr.val));
sb.append(",");
}
que.add(curr.left);
que.add(curr.right);
}
char c = sb.charAt(sb.length() - 1);
do {
sb.deleteCharAt(sb.length() - 1);
c = sb.charAt(sb.length() - 1);
} while (c == '#' || c == ',');
//System.out.println(sb.toString());
return sb.toString();
}
// Decodes your encoded data to tree.
public TreeNode deserialize(String data) {
if (data == "") return null;
String[] vals = data.split(",");
Queue<TreeNode> que = new LinkedList<>();
TreeNode root = new TreeNode(Integer.valueOf(vals[0]));
que.add(root);
TreeNode curr = null;
boolean isLeft = true;
for (int index = 1; index < vals.length; index++) {
if (vals[index].equals("#")) {
curr = null;
} else {
curr = new TreeNode(Integer.valueOf(vals[index]));
que.add(curr);
}
if (isLeft) {
que.peek().left = curr;
} else {
que.poll().right = curr;
}
isLeft = !isLeft;
}
return root;
}
}
Version #5 Byte Manipulation
这个方法是把Integer直接变成string给改成byte 表示法,可以压缩space
String ->
-2^31 = -2147483648 -> 11 chars
https://www.javamex.com/tutorials/memory/string_memory_usage.shtml
Byte -> 0xFFFFFFFF
4 bytes
No string-integer conversion needed
如果是 int -> byte[] -> char[] 的话,转换回来的时候
如果不
// return (int) ((data[0] & 0xff) << 24)
// | ((data[1] & 0xff) << 16)
// | ((data[2] & 0xff) << 8)
// | (data[3] & 0xff);
就会出错
然而如果直接 int -> char[]就不需要考虑这个问题,因为在int -> char[] 的时候已经
(char)((x >> 24) & 0xff),
(char)((x >> 16) & 0xff),
(char)((x >> 8) & 0xff),
(char)(x & 0xff)
了
99.15 %
public class Codec {
private char NULL_VALUE = '0';
private char NOT_NULL_VALUE = '1';
// Encodes a tree to a single string.
public String serialize(TreeNode root) {
StringBuilder sb = new StringBuilder();
seHelper(root, sb);
return sb.toString();
}
private void seHelper(TreeNode node, StringBuilder sb) {
if (node == null) {
sb.append(NULL_VALUE);
return;
}
char[] array = int2Bytes(node.val);
sb.append(NOT_NULL_VALUE).append(array[0]).append(array[1]).append(array[2]).append(array[3]);
seHelper(node.left, sb);
seHelper(node.right, sb);
}
private char[] int2Bytes(int x) {
return new char[]{
(char)((x >> 24) & 0xff),
(char)((x >> 16) & 0xff),
(char)((x >> 8) & 0xff),
(char)(x & 0xff)
};
}
// Decodes your encoded data to tree.
private int index;
public TreeNode deserialize(String data) {
index = 0;
return deHelper(data.toCharArray());
}
private TreeNode deHelper(char[] data) {
if (data[index++] == NULL_VALUE) {
return null;
}
TreeNode node = new TreeNode(bytes2Int(new char[]{
data[index],
data[index + 1],
data[index + 2],
data[index + 3]
}));
index += 4;
node.left = deHelper(data);
node.right = deHelper(data);
return node;
}
private int bytes2Int(char[] data) {
return (int) (data[0] << 24)
| (data[1] << 16)
| (data[2] << 8)
| data[3];
}
}
Version #3 Iteration with Stack
二刷
看一刷的不知道自己在写什么。。。为什么需要一个boolean来判断是不是left?
Stack 加的时候注意是先左后右
Stack deserialize的时候,都是向左走到底,然后向右跳一个
39.88 %
public class Codec {
// Encodes a tree to a single string.
public String serialize(TreeNode root) {
if (root == null) {
return null;
}
StringBuilder sb = new StringBuilder();
Deque<TreeNode> stack = new LinkedList<>();
stack.addFirst(root);
while (!stack.isEmpty()) {
TreeNode curr = stack.removeFirst();
if (curr == null) {
sb.append("#,");
} else {
sb.append(curr.val + ",");
stack.addFirst(curr.right);
stack.addFirst(curr.left);
}
}
System.out.println(sb.toString());
return sb.toString();
}
// Decodes your encoded data to tree.
public TreeNode deserialize(String data) {
if (data == null || data.length() == 0) {
return null;
}
String[] strs = data.split(",");
Deque<TreeNode> stack = new LinkedList<>();
int pointer = 0;
if (strs.length == 0 || strs[pointer].equals("#")) {
return null;
}
TreeNode root = new TreeNode(Integer.valueOf(strs[0]));
TreeNode curr = root;
stack.addFirst(root);
pointer++;
while (pointer < strs.length) {
while (curr != null) {
stack.addFirst(curr);
curr.left = strs[pointer].equals("#") ? null : new TreeNode(Integer.valueOf(strs[pointer]));
pointer++;
curr = curr.left;
}
curr = stack.removeFirst();
curr.right = strs[pointer].equals("#") ? null : new TreeNode(Integer.valueOf(strs[pointer]));
pointer++;
curr = curr.right;
}
return root;
}
}
一刷
Iteration desirialization 好难啊,写了好久好久好久
stack里面放的是已经连完左节点但是等待右subtree的点
curr代表的是当下等待连左节点的点
如果遇到null
1st -> 证明当前curr的left subtree是null
当前curr已经是Left most node
开始往外pop
2nd -> 在pop round,pop出的点是waiting for its right subtree
此时遇到null 证明当前点的right subtree是NULL
直接继续pop
37.48 %
public class Codec {
private static final String DIVIDER = "/";
private static final String NULL = "null";
// Encodes a tree to a single string.
public String serialize(TreeNode root) {
if (root == null) return null;
StringBuilder sb = new StringBuilder();
Stack<TreeNode> stack = new Stack<>();
TreeNode curr = root;
while (curr != null || !stack.isEmpty()) {
if (curr != null) {
sb.append(curr.val);
sb.append(DIVIDER);
stack.push(curr);
curr = curr.left;
} else {
sb.append(NULL + DIVIDER);
curr = stack.pop();
curr = curr.right;
}
}
sb.deleteCharAt(sb.length() - 1);
return sb.toString();
}
// Decodes your encoded data to tree.
public TreeNode deserialize(String data) {
if (data == null) return null;
String[] strs = data.trim().split(DIVIDER);
int index = 0;
TreeNode root = new TreeNode(Integer.valueOf(strs[index++]));
Stack<TreeNode> stack = new Stack<>();
TreeNode curr = root;
stack.push(curr);
int n = strs.length;
// Nodes in stack -> waiting for their right subtree
// curr -> waiting for its left subtree
while (index < n) {
while (index < n && !strs[index].equals(NULL)) {
curr.left = new TreeNode(Integer.valueOf(strs[index++]));
curr = curr.left;
stack.push(curr);
}
// Top nodes left subtree is null, get the next candidate node
while (index < n && strs[index].equals(NULL)) {
curr = stack.pop();
index++;
}
// strs[index] is not NULL
if (index < n) {
curr.right = new TreeNode(Integer.valueOf(strs[index++]));
curr = curr.right;
stack.push(curr);
}
}
return root;
}
}
Version #4 Recursion DFS
Pre-Order Traversal
注意pointer是一个global变量,每一次recursion的当前层负责给pointer + 1
二刷
94.28 %
public class Codec {
// Encodes a tree to a single string.
public String serialize(TreeNode root) {
StringBuilder sb = new StringBuilder();
seHelper(root, sb);
return sb.toString();
}
private void seHelper(TreeNode node, StringBuilder sb) {
if (node == null) {
sb.append("#,");
return;
}
sb.append(node.val + ",");
seHelper(node.left, sb);
seHelper(node.right, sb);
}
// Decodes your encoded data to tree.
public TreeNode deserialize(String data) {
if (data == null || data.length() == 0) {
return null;
}
String[] strs = data.split(",");
int[] pointer = new int[]{0};
return deHelper(strs, pointer);
}
private TreeNode deHelper(String[] strs, int[] pointer) {
if (strs[pointer[0]].equals("#")) {
pointer[0]++;
return null;
}
TreeNode node = new TreeNode(Integer.valueOf(strs[pointer[0]]));
pointer[0]++;
node.left = deHelper(strs, pointer);
node.right = deHelper(strs, pointer);
return node;
}
}
Version #1 jiuzhang Version BFS with Queue
二刷
49.87 %
public class Codec {
// Encodes a tree to a single string.
public String serialize(TreeNode root) {
StringBuilder sb = new StringBuilder();
Queue<TreeNode> que = new LinkedList<>();
if (root == null) {
return null;
}
que.offer(root);
while (!que.isEmpty()) {
TreeNode curr = que.poll();
if (curr == null) {
sb.append("#,");
} else {
sb.append(curr.val + ",");
que.offer(curr.left);
que.offer(curr.right);
}
}
return sb.toString();
}
// Decodes your encoded data to tree.
public TreeNode deserialize(String data) {
if (data == null || data.length() == 0) {
return null;
}
String[] strs = data.split(",");
Queue<TreeNode> que = new LinkedList<>();
if (strs.length == 0) {
return null;
}
int pointer = 0;
TreeNode root = new TreeNode(Integer.valueOf(strs[pointer++]));
que.offer(root);
while (!que.isEmpty()) {
TreeNode curr = que.poll();
TreeNode left = null;
if (!strs[pointer].equals("#")) {
left = new TreeNode(Integer.valueOf(strs[pointer]));
que.offer(left);
}
pointer++;
curr.left = left;
TreeNode right = null;
if (!strs[pointer].equals("#")) {
right = new TreeNode(Integer.valueOf(strs[pointer]));
que.offer(right);
}
pointer++;
curr.right = right;
}
return root;
}
}
一刷
49.35 %
public class Codec {
// Encodes a tree to a single string.
public String serialize(TreeNode root) {
if (root == null) return "{}";
ArrayList<TreeNode> que = new ArrayList<>();
que.add(root);
TreeNode curr = null;
for (int i = 0; i < que.size(); i++) {
curr = que.get(i);
if (curr == null) continue;
que.add(curr.left);
que.add(curr.right);
}
StringBuilder sb = new StringBuilder();
sb.append("{");
curr = que.get(0);
int index = 1;
sb.append(String.valueOf(curr.val));
while (index < que.size()) {
curr = que.get(index);
index++;
sb.append(",");
if (curr == null) sb.append("#");
else sb.append(String.valueOf(curr.val));
}
sb.append("}");
return sb.toString();
}
// Decodes your encoded data to tree.
public TreeNode deserialize(String data) {
if (data.equals("{}")) {
return null;
}
String[] vals = data.substring(1, data.length() - 1).split(",");
ArrayList<TreeNode> queue = new ArrayList<TreeNode>();
TreeNode root = new TreeNode(Integer.parseInt(vals[0]));
queue.add(root);
int index = 0;
boolean isLeftChild = true;
for (int i = 1; i < vals.length; i++) {
if (!vals[i].equals("#")) {
TreeNode node = new TreeNode(Integer.parseInt(vals[i]));
if (isLeftChild) {
queue.get(index).left = node;
} else {
queue.get(index).right = node;
}
queue.add(node);
}
if (!isLeftChild) {
index++;
}
isLeftChild = !isLeftChild;
}
return root;
}
}
// Your Codec object will be instantiated and called as such:
// Codec codec = new Codec();
// codec.deserialize(codec.serialize(root));
Version #2
57.60 %
自己改进了一下感觉比上个方法简洁一点 就是传统地用queue
上个方法里面用ArrayList作为Queue然后用get(index) 来代替queue.poll()感觉也挺有意思的
注意!string == "#"是不对的 必须string.equals("#");
public class Codec {
// Encodes a tree to a single string.
public String serialize(TreeNode root) {
if (root == null) return "";
StringBuilder sb = new StringBuilder();
Queue<TreeNode> que = new LinkedList<>();
que.add(root);
TreeNode curr = null;
while (!que.isEmpty()) {
curr = que.poll();
if (curr == null) {
sb.append("#,");
continue;
} else {
sb.append(String.valueOf(curr.val));
sb.append(",");
}
que.add(curr.left);
que.add(curr.right);
}
char c = sb.charAt(sb.length() - 1);
do {
sb.deleteCharAt(sb.length() - 1);
c = sb.charAt(sb.length() - 1);
} while (c == '#' || c == ',');
//System.out.println(sb.toString());
return sb.toString();
}
// Decodes your encoded data to tree.
public TreeNode deserialize(String data) {
if (data == "") return null;
String[] vals = data.split(",");
Queue<TreeNode> que = new LinkedList<>();
TreeNode root = new TreeNode(Integer.valueOf(vals[0]));
que.add(root);
TreeNode curr = null;
boolean isLeft = true;
for (int index = 1; index < vals.length; index++) {
if (vals[index].equals("#")) {
curr = null;
} else {
curr = new TreeNode(Integer.valueOf(vals[index]));
que.add(curr);
}
if (isLeft) {
que.peek().left = curr;
} else {
que.poll().right = curr;
}
isLeft = !isLeft;
}
return root;
}
}
373. Find K Pairs with Smallest Sums
Version #1 MinHeap with Lambda
41.23 %
class Solution {
public List<int[]> kSmallestPairs(int[] nums1, int[] nums2, int k) {
List<int[]> result = new ArrayList<>();
if (nums1 == null || nums1.length == 0 || nums2 == null || nums2.length == 0) return result;
// minHeap -> always poll out the minimum sum and add its adjacent sums
PriorityQueue<int[]> minHeap = new PriorityQueue<>(10, (pairA, pairB) ->
(nums1[pairA[0]] + nums2[pairA[1]]) - (nums1[pairB[0]] + nums2[pairB[1]]));
minHeap.offer(new int[]{0, 0});
while (k-- > 0 && !minHeap.isEmpty()) {
int[] curr = minHeap.poll();
int i1 = curr[0];
int i2 = curr[1];
result.add(new int[]{nums1[i1], nums2[i2]});
if (i1 == 0 && (i2 + 1 < nums2.length)) minHeap.offer(new int[]{i1, i2 + 1});
if (i1 + 1 < nums1.length) minHeap.offer(new int[]{i1 + 1, i2});
}
return result;
}
}
Version #2 Self-defined class -> Tuple with is own compareTo method
LC上看到的,拿过来做reference
如果lambda写不好可以参考这个方法
92.17 %
"public class Solution {
public List<int[]> kSmallestPairs(int[] nums1, int[] nums2, int k) { PriorityQueue<Tuple> pq = new PriorityQueue<Tuple>(); int m = nums1.length, n = nums2.length; List<int[]> res = new ArrayList<int[]>(); if(nums1 == null || nums1.length == 0 || nums2 == null || nums2.length == 0 || k <= 0) return res; for(int j = 0; j <= n-1; j++) pq.offer(new Tuple(0, j, nums1[0]+nums2[j])); for(int i = 0; i < Math.min(k, m *n); i++) { Tuple t = pq.poll(); res.add(new int[]{nums1[t.x], nums2[t.y]}); if(t.x == m - 1) continue; pq.offer(new Tuple (t.x + 1, t.y, nums1[t.x + 1] + nums2[t.y])); } return res; } } class Tuple implements Comparable<Tuple> { int x, y, val; public Tuple (int x, int y, int val) { this.x = x; this.y = y; this.val = val; } @Override public int compareTo (Tuple that) { return this.val - that.val; } }"
41.23 %
class Solution {
public List<int[]> kSmallestPairs(int[] nums1, int[] nums2, int k) {
List<int[]> result = new ArrayList<>();
if (nums1 == null || nums1.length == 0 || nums2 == null || nums2.length == 0) return result;
// minHeap -> always poll out the minimum sum and add its adjacent sums
PriorityQueue<int[]> minHeap = new PriorityQueue<>(10, (pairA, pairB) ->
(nums1[pairA[0]] + nums2[pairA[1]]) - (nums1[pairB[0]] + nums2[pairB[1]]));
minHeap.offer(new int[]{0, 0});
while (k-- > 0 && !minHeap.isEmpty()) {
int[] curr = minHeap.poll();
int i1 = curr[0];
int i2 = curr[1];
result.add(new int[]{nums1[i1], nums2[i2]});
if (i1 == 0 && (i2 + 1 < nums2.length)) minHeap.offer(new int[]{i1, i2 + 1});
if (i1 + 1 < nums1.length) minHeap.offer(new int[]{i1 + 1, i2});
}
return result;
}
}
Version #2 Self-defined class -> Tuple with is own compareTo method
LC上看到的,拿过来做reference
如果lambda写不好可以参考这个方法
92.17 %
"public class Solution {
public List<int[]> kSmallestPairs(int[] nums1, int[] nums2, int k) { PriorityQueue<Tuple> pq = new PriorityQueue<Tuple>(); int m = nums1.length, n = nums2.length; List<int[]> res = new ArrayList<int[]>(); if(nums1 == null || nums1.length == 0 || nums2 == null || nums2.length == 0 || k <= 0) return res; for(int j = 0; j <= n-1; j++) pq.offer(new Tuple(0, j, nums1[0]+nums2[j])); for(int i = 0; i < Math.min(k, m *n); i++) { Tuple t = pq.poll(); res.add(new int[]{nums1[t.x], nums2[t.y]}); if(t.x == m - 1) continue; pq.offer(new Tuple (t.x + 1, t.y, nums1[t.x + 1] + nums2[t.y])); } return res; } } class Tuple implements Comparable<Tuple> { int x, y, val; public Tuple (int x, int y, int val) { this.x = x; this.y = y; this.val = val; } @Override public int compareTo (Tuple that) { return this.val - that.val; } }"
Monday, September 18, 2017
652. Find Duplicate Subtrees
Version #2
基本思路还是差不多,比Version#1好一些
map.getOrDefault(curr, 0) 这个method 用着很不错哎 Mark一下
53.39 %
HashMap key-> String, value -> count of Nodes with same string
If and only if count == 2, we add current node into result list
if (count == 1) duplicate hasn't been found yet
if (count > 2) this result has already added into the result list
class Solution {
public List<TreeNode> findDuplicateSubtrees(TreeNode root) {
List<TreeNode> result = new ArrayList<>();
if (root == null) return result;
Map<String, Integer> map = new HashMap<>();
dfsHelper(root, map, result);
return result;
}
private String dfsHelper(TreeNode root, Map<String, Integer> map, List<TreeNode> result) {
if (root == null) return "#";
String curr = root.val + "/" + dfsHelper(root.left, map, result) + "/" + dfsHelper(root.right, map, result);
if (map.getOrDefault(curr, 0) == 1) result.add(root);
map.put(curr, map.getOrDefault(curr, 0) + 1);
return curr;
}
}
Version #1
HashMap 的key是String,value是TreeNode
因为一组相同的subTree只记录其中一个,所以用一个HashSet记录看到过的subTree Root
看了Version#2 的答案感觉不如Version#2写的好
29.41 %
class Solution {
public List<TreeNode> findDuplicateSubtrees(TreeNode root) {
// key-serialized string of subtree, value-the node
if (root == null) return new ArrayList<TreeNode>();
Map<String, TreeNode> map = new HashMap<>();
Set<TreeNode> set = new HashSet<>();
// TODO
dfsHelper(root, map, set);
return new ArrayList<TreeNode>(set);
}
private String dfsHelper(TreeNode root, Map<String, TreeNode> map, Set<TreeNode> set) {
if (root == null) {
return "#";
}
String curr = root.val + "/" + dfsHelper(root.left, map, set) + "/" + dfsHelper(root.right, map, set);
if (map.containsKey(curr)) {
set.add(map.get(curr));
} else {
map.put(curr, root);
}
return curr;
}
}
基本思路还是差不多,比Version#1好一些
map.getOrDefault(curr, 0) 这个method 用着很不错哎 Mark一下
53.39 %
HashMap key-> String, value -> count of Nodes with same string
If and only if count == 2, we add current node into result list
if (count == 1) duplicate hasn't been found yet
if (count > 2) this result has already added into the result list
class Solution {
public List<TreeNode> findDuplicateSubtrees(TreeNode root) {
List<TreeNode> result = new ArrayList<>();
if (root == null) return result;
Map<String, Integer> map = new HashMap<>();
dfsHelper(root, map, result);
return result;
}
private String dfsHelper(TreeNode root, Map<String, Integer> map, List<TreeNode> result) {
if (root == null) return "#";
String curr = root.val + "/" + dfsHelper(root.left, map, result) + "/" + dfsHelper(root.right, map, result);
if (map.getOrDefault(curr, 0) == 1) result.add(root);
map.put(curr, map.getOrDefault(curr, 0) + 1);
return curr;
}
}
Version #1
HashMap 的key是String,value是TreeNode
因为一组相同的subTree只记录其中一个,所以用一个HashSet记录看到过的subTree Root
看了Version#2 的答案感觉不如Version#2写的好
29.41 %
class Solution {
public List<TreeNode> findDuplicateSubtrees(TreeNode root) {
// key-serialized string of subtree, value-the node
if (root == null) return new ArrayList<TreeNode>();
Map<String, TreeNode> map = new HashMap<>();
Set<TreeNode> set = new HashSet<>();
// TODO
dfsHelper(root, map, set);
return new ArrayList<TreeNode>(set);
}
private String dfsHelper(TreeNode root, Map<String, TreeNode> map, Set<TreeNode> set) {
if (root == null) {
return "#";
}
String curr = root.val + "/" + dfsHelper(root.left, map, set) + "/" + dfsHelper(root.right, map, set);
if (map.containsKey(curr)) {
set.add(map.get(curr));
} else {
map.put(curr, root);
}
return curr;
}
}
595. Big Countries
87.60 %
SELECT World.name, World.population, World.area
FROM World
WHERE World.area > 3000000
OR World.population > 25000000
Sunday, September 17, 2017
414. Third Maximum Number
default minHeap
If we need a maxHeap, we can write
PriorityQueue<Integer> queue = new PriorityQueue<>(10, Collections.reverseOrder());
Version #1 Priority Queue18.80 %
class Solution {
public int thirdMax(int[] nums) {
if (nums == null || nums.length == 0) throw new IllegalArgumentException();
PriorityQueue<Integer> minHeap = new PriorityQueue<>();
Set<Integer> visited = new HashSet<>();
int max = nums[0];
for (int num : nums) {
if (visited.contains(num)) continue;
max = Math.max(num, max);
if (minHeap.size() < 3) {
minHeap.offer(num);
} else {
if (num >= minHeap.peek()) {
minHeap.poll();
minHeap.offer(num);
}
}
visited.add(num);
}
return minHeap.size() == 3 ? minHeap.peek() : max;
}
}
Version #2 Direct Compare
以为很简单,其实爆炸难写
难点主要是duplicate和不够3个distinct Integers的处理
一开始我把三个值都设成num[0], 发现错的离谱,比如[3, 2, 1] 如果一开始都是3的话,后面就没法Update了
所以一开始都设成null
然后又有问题,譬如second是null,不能无脑把second设成当前值,因为有可能当前的值等于first,就会有duplicate
这里面具体的逻辑还是没搞清,看到答案写先和三个值比一下,如果相等就continue,觉得很有道理
但是自己写的时候 nums[i] == first 这种写法是会报NulPointerException的
所以应该写成!! Integer n : nums .... n.equals(first)
可以说非常考基本功了
33.14 %
class Solution {
public int thirdMax(int[] nums) {
if (nums == null || nums.length == 0) throw new IllegalArgumentException();
Integer first = null;
Integer second = null;
Integer third = null;
//case1 case2 case3 case4
// 1 2 3
for (Integer n : nums) {
// if nums[i] == 1st/2nd/3rd, we do nothing
if (n.equals(first) || n.equals(second) || n.equals(third)) continue;
if (first == null || n > first) {
third = second;
second = first;
first = n;
} else if (second == null || n > second) {
third = second;
second = n;
} else if (third == null || n > third) {
third = n;
}
}
return third == null ? first : third;
}
}
Subscribe to:
Posts (Atom)
