我在Hackerrank上正在做this problem。问题摘要是:
您正在尝试重建[1,10 ^ 6]范围内的M个不同整数的序列。给予1&lt; = N <= 10 ^ 3个长度为2 <= K <= 10 ^ 3的子序列。如果可能有两个序列,则返回字典缩小的序列。
我的算法如下:
为每个不同的整数创建一个顶点。将它们存储在哈希映射中。
对于每一行,如果i
位于行前j
之前,请添加i
到j
的边。跟踪每个顶点的不确定性。
创建一个优先级队列,其关键是每个顶点的值。将所有顶点排列为indegree 0.
队列非空时:弹出顶部顶点。减少每个孩子的不确定性。
我的回答是正确的,但我在较大的测试用例上超出了时间限制。我认为优先级队列是瓶颈,但我想不出一种方法来保持顶点按值排序小于O(log n)
。我的代码如下,将Vertex类排除在外以使其更短 - 它主要只是getter和setter:
class FavoriteSequence {
private Map<Integer, Vertex> seen;
public void solve(int testNumber, Scanner in, PrintWriter out) {
int numRows = in.nextInt();
seen = new HashMap<>();
for (int i = 0; i < numRows; i++) {
int numInRow = in.nextInt();
List<Vertex> row = IntStream.range(0, numInRow).mapToObj(x -> getVert(in.nextInt())).collect(
Collectors.toList());
int idx = 0;
for (Vertex v : row) {
v.incInDegree(idx);
v.addChildren(row.subList(++idx, numInRow));
}
}
List<String> ans = new LinkedList<>();
Queue<Vertex> bfsQ = new PriorityQueue<>(new Comparator<Vertex>() {
public int compare(Vertex o1, Vertex o2) {
int valCmp = Integer.compare(o1.getValue(), o2.getValue());
return valCmp;
}
});
bfsQ.addAll(seen.values().stream().filter(c -> c.getInDegree() == 0).collect(Collectors.toList()));
while (!bfsQ.isEmpty()) {
Vertex me = bfsQ.poll();
ans.add(Integer.toString(me.getValue()));
for (List<Vertex> cs : me.getChildrens()) {
for (Vertex c : cs) {
if (c.decInDegree() == 0) {
bfsQ.add(c);
}
}
}
}
out.println(String.join(" ", ans));
}
private Vertex getVert(int idx) {
Vertex me = seen.get(idx);
if (me == null) {
me = new Vertex(idx);
seen.put(idx, me);
}
return me;
}
}
我做得太慢了?为了使其具体化,我提供了我的代码,但我真的在寻找算法的答案。
答案 0 :(得分:2)
如果我没弄错,这段代码
int idx = 0;
for (Vertex v : row) {
v.incInDegree(idx);
v.addChildren(row.subList(++idx, numInRow));
}
添加弧,其数量与子序列的长度成二次方增长。实际上,只需要在传递减少中添加弧,即从子序列的每个元素添加到其直接后继者。