【发布时间】:2020-05-01 19:56:50
【问题描述】:
这个问题与 HackerRank 上的this challenge 有关。它似乎在某些情况下失败了,但我不清楚算法有什么问题(很多人似乎对超时有问题,这不是问题,一切都运行得很快,所有对我可见的情况都通过了,所以我没有失败的具体案例)。
算法工作原理的基本概要如下: 首先确保 Alice 还没有超过现有的最高分(退化案例),如果她只是告诉全世界她从头到尾都是第一名。否则,排行榜上至少有一个分数超过了 Alice 的第一次尝试。
- 从分数列表从最高开始,直到我们找到适合 Alice 的位置,并记录一路上超过 Alice 初始分数的分数。
- 如果我们在为 Alice 的最低分数找到位置之前到达分数列表的末尾,假设列表底部有一个与 Alice 的第一个分数匹配的分数(这只是为了方便主循环并减少问题到爱丽丝的第一个分数在列表中的某个地方)
此时,我们有一个(排序的)分数数组及其相关的排名,rankAry[r - 1] 是 Alice 在第一个 while 循环之后的 if 子句结束时达到排名 r 所需的最低分数.
从那里开始,主算法接管了我们遍历 Alice 的分数的位置,并通过与我们之前设置为 rankAry 的分数数组中的基准进行比较来记录她的排名。 curRank 是我们在每个阶段的候选排名,在这个循环开始时(通过构建)我们肯定已经达到。
- 如果我们处于排名 1,我们将永远更多,所以只需将当前排名填充为 1 并继续前进。
- 如果我们目前与当前基准测试并驾齐驱,并且这还没有结束,请继续查看下一个基准,如果我们也击败下一个基准,则减少当前基准位置并迭代李>
- 一旦结束,我们就找到了我们要取代的那个,我们不能再取代任何东西,所以将这个排名分配给这个分数并重复直到完成
据我所知,这可以正确处理所有情况,即使 Alice 在分数的基准之间有重复值或增加,我们应该保持相同的排名,直到我们达到新的基准,但网站反馈表明必须在某处成为一个错误。
我能找到的所有其他方法似乎都与每次进行二进制搜索以查找分数相比有所不同,但我不想每次都不断搜索而只使用辅助空间,所以我我对可能发生的事情感到有些困惑。
static int[] climbingLeaderboard(int[] scores, int[] alice) {
int[] res = new int[alice.Length];
if (scores.Length == 0 || alice[0] >= scores[0]) { //degenerate cases
for (int i = 0; i < alice.Length; ++i) {
res[i] = 1;
}
return res;
}
int[] rankAry = new int[scores.Length + 1];
rankAry[0] = scores[0]; //top score rank
int curPos = 1; //start at the front and move down
int curRank = 1; //initialize
//initialize from the front. This way we can figure out ranks as we go
while (curPos < scores.Length && scores[curPos] > alice[0]) {
if (scores[curPos] < scores[curPos-1]) {
rankAry[curRank] = scores[curPos]; //update the rank break point
curRank++; //moved down in rank
}
curPos++; //move down the array
}
if (curPos == scores.Length) { //smallest score still bigger than Alice's first
rankAry[curRank] = alice[0]; //pretend there was a virtual value at the end
curRank++; //give rank Alice will have for first score when we get there
}
for (int i = 0; i < alice.Length; ++i) {
if (curRank == 1) { //if we're at the top, we're going to stay there
res[i] = 1;
continue;
}
//Non-degenerate cases
while (alice[i] >= rankAry[curRank - 1]) {
if (curRank == 1 || alice[i] < rankAry[curRank - 2]) {
break;
}
curRank--;
}
res[i] = curRank;
}
return res;
}
【问题讨论】:
标签: c# algorithm dynamic-programming