我在最近的招聘挑战中遇到了这个问题:
给出N
个字符串,每个字符串为'0'-'9'数字和一个整数K
。两个玩家A和B玩游戏如下:
A首先播放,并选择前K
个字符串中的任何字符串。
下一位选手B被允许从其最后一个回合中选择的字符串开始,该数字等于在最后一次拾取的字符串A中最后一位的数字,在接下来的K
字符串中,由A拾取。如果A选择了索引为i
的“ 045679”,则B只能从索引i+1
到i+K
的字符串中选择以数字'9'开头的字符串。
一个不能选弦的人输了
两个球员都发挥出最佳状态。
我们需要告诉获胜者以及获胜者拾取的最小字符串索引。
我以前已经看到过此类问题,并且需要对如何考虑此类问题提出建议。预先感谢。
答案 0 :(得分:0)
这类似于nim的游戏。您必须从获胜位置转到输掉位置才能继续获胜。
我们可以倒退:如果最后一个玩家拿走了最后一个字符串,那么现在移动的玩家正在输球;如果选择了最后一个字符串,则走动的玩家正在输球,除非最后一个字符串的最后一位数字以及最后一个字符串匹配的起始数字,依此类推。
通过正确的实现,您可以获得O(n)的时间复杂度和O(k)的空间复杂度,因为您只需要跟踪大小为k的窗口。像这样:
// return a winning first move or -1 if there is none
public int solve(String[] strings, int k) {
Queue<Boolean> q = new Deque<>();
int[] lossCount = new int[10];
for (int i = strings.length - 1; i >= 0; i--) {
int start = strings[i].charAt(0) - '0';
int end = strings[i].charAt(strings[i].length() - 1) - '0';
if (i + k + 1 < strings.length && !q.remove())
lossCount[strings[i + k + 1].charAt(0) - '0']--;
boolean win = lossCount[end] == 0;
if (!win)
lossCount[start]++;
else if (i < k)
return i;
q.add(win);
}
return -1;
}