推特

迎难而上,祝我好运。面朝大海,春暖花开。

OA

  • 总共有n个节点,给两个List表示从first到second有一条undirected edge,再给一个values数组表示对应编号的node的值。然后给一堆query,找这些编号为root的子树中素数的节点count。注意编号为1的节点作为根。
  • 直接把自己做的存下来了:利用1作为根这个条件用BFS构建多叉树,然后用递归count有多少个素数。为了避免重复计算,用了memo(一个用在判断prime,一个用在计数prime node).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
static class TreeNode {
int id;
int val;
List<TreeNode> children;
public TreeNode(int id, int val) {
this.id = id;
this.val = val;
children = new ArrayList<>();
}
}
// Complete the primeQuery function below.
static List<Integer> primeQuery(int n, List<Integer> first, List<Integer> second, List<Integer> values, List<Integer> queries) {
if (first == null || second == null || first.size() != second.size() || values.size() != n) {
return null;
}
Map<Integer, Set<Integer>> edgeMap = new HashMap<>(); // map from node-id to a set of its neighbors' id
for (int i = 0; i < first.size(); i++) {
edgeMap.putIfAbsent(first.get(i), new HashSet<>());
edgeMap.putIfAbsent(second.get(i), new HashSet<>());
edgeMap.get(first.get(i)).add(second.get(i)); // undirected: add the mapping relation to both sides
edgeMap.get(second.get(i)).add(first.get(i));
}

Map<Integer, TreeNode> id2Node = new HashMap<>(); // map from id to actual TreeNode object
TreeNode root = constructTree(edgeMap, values, id2Node);
List<Integer> ans = new ArrayList<>();
Map<Integer, Integer> countCache = new HashMap<>();
Map<Integer, Boolean> primeCache = new HashMap<>();
for (int query : queries) {
ans.add(getPrimeCount(id2Node.get(query), countCache, primeCache));
}
return ans;
}

// use BFS to constrct tree
static TreeNode constructTree(Map<Integer, Set<Integer>> edgeMap, List<Integer> values,
Map<Integer, TreeNode> id2Node) {
Queue<TreeNode> q = new LinkedList<>();
TreeNode root = new TreeNode(1, values.get(0)); // start from root with id 1
id2Node.put(1, root);
q.add(root);
while (!q.isEmpty()) {
TreeNode curr = q.poll();
Set<Integer> childIds = edgeMap.get(curr.id); // get all its neighbors' id
if (childIds == null) {
continue;
}
for (int childId : childIds) {
TreeNode child = new TreeNode(childId, values.get(childId - 1));
id2Node.put(childId, child); // from id to node
q.offer(child);
curr.children.add(child); // add neighbor node into curr node's children list
edgeMap.get(childId).remove(curr.id); // remove curr's id from the neighbor's "neighbor set"
}
edgeMap.remove(curr.id); // finish process curr node, remove it from edgeMap
}
return root;
}

// given a TreeNode, return the count of nodes with prime value
static int getPrimeCount(TreeNode node, Map<Integer, Integer> countCache,
Map<Integer, Boolean> primeCache) {
if (node == null) {
return 0;
}
if (countCache.containsKey(node.id)) { // hit in cache, simply return
return countCache.get(node.id);
}
int count = isPrime(node.val, primeCache) ? 1 : 0;
for (TreeNode child : node.children) { // get prime count at each child
count += getPrimeCount(child, countCache, primeCache);
}
countCache.put(node.id, count); // put into cache
return count;
}

static boolean isPrime(int val, Map<Integer, Boolean> primeCache) {
if (primeCache.containsKey(val)) { // hit in cache, simply return
return primeCache.get(val);
}
if (val <= 1) {
primeCache.put(val, false);
return false;
}
int limit = (int) Math.sqrt(val);
for (int i = 2; i <= limit; i++) {
if (val % i == 0) {
primeCache.put(val, false);
return false;
}
}
primeCache.put(val, true);
return true;
}