这个找“最近一个”对方行权成员的操作既可以使用「有序集合」来做,也可以使用「循环队列」来做。
先说使用「有序集合」的做法。
起始我们先将 s
中的 Radiant
和 Dire
分别存入有序集合 rs
和 ds
当中,然后从前往后模拟消除过程,过程中使用 idx
代表当前处理到的成员下标,使用 set
记录当前哪些成员已被消除。
当轮到 s[idx]
行权时(若 s[idx]
已被消除,则跳过本轮),从对方的有序队列中取出 「首个大于等于 idx
的下标」(取出代表移除);若对方的有序序列不存在该下标,而行权过程又是循环进行的,说明此时下一个行权的对方成员是 「首个大于等于
」 的下标,我们对其进行取出消除,随后往后继续决策。
Java 代码:
class Solution {
public String predictPartyVictory(String s) {
TreeSet<Integer> rs = new TreeSet<>(), ds = new TreeSet<>();
int n = s.length();
for (int i = 0; i < n; i++) {
if (s.charAt(i) == 'R') rs.add(i);
else ds.add(i);
}
Set<Integer> set = new HashSet<>();
int idx = 0;
while (rs.size() != 0 && ds.size() != 0) {
if (!set.contains(idx)) {
TreeSet<Integer> temp = null;
if (s.charAt(idx) == 'R') temp = ds;
else temp = rs;
Integer t = temp.ceiling(idx);
if (t == null) t = temp.ceiling(0);
set.add(t);
temp.remove(t);
}
idx = (idx + 1) % n;
}
return rs.size() != 0 ? "Radiant" : "Dire";
}
}
不难发现,虽然将所有成员存入有序集合和取出的复杂度均为 ,但整体复杂度仍是大于 。
因为我们在每一轮的消除中,从 idx
位置找到下一个决策者,总是需要遍历那些已被消除的位置,而该无效遍历操作可使用「循环队列」优化。