C# HackerRank登上排行榜

C# HackerRank登上排行榜,c#,algorithm,dynamic-programming,C#,Algorithm,Dynamic Programming,这个问题与黑客银行有关。它似乎在某些情况下失败了,但我不清楚算法出了什么问题(许多人似乎在超时方面有问题,这在这里不是问题,一切都运行得很快,我看到的所有情况都通过了,所以我没有失败的具体情况) 算法工作原理的基本概述如下: 首先,如果爱丽丝只是告诉全世界她自始至终都是1,那么要确保她还没有赢得现有的最高分数(堕落案例)。否则,排行榜上至少有一分击败了Alice的第一次尝试 从最高分开始沿着分数表往下走,直到我们找到一个Alice适合的地方,并记录一路上超过Alice初始分数的分数 如果我们在

这个问题与黑客银行有关。它似乎在某些情况下失败了,但我不清楚算法出了什么问题(许多人似乎在超时方面有问题,这在这里不是问题,一切都运行得很快,我看到的所有情况都通过了,所以我没有失败的具体情况)

算法工作原理的基本概述如下: 首先,如果爱丽丝只是告诉全世界她自始至终都是1,那么要确保她还没有赢得现有的最高分数(堕落案例)。否则,排行榜上至少有一分击败了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;
    }
static int[]攀登排行榜(int[]得分,int[]爱丽丝){
int[]res=新的int[alice.Length];
如果(scores.Length==0 | | alice[0]>=scores[0]){//退化情况
for(int i=0;ialice[0]){
如果(分数[curPos]<分数[curPos-1]){
rankAry[curRank]=分数[curPos];//更新排名断点
curRank++;//排名下降
}
curPos++;//向下移动阵列
}
如果(curPos==scores.Length){//最小的分数仍然比Alice的第一个分数大
rankAry[curRank]=alice[0];//假装最后有一个虚拟值
curRank++;//给Alice排名,当我们到达那里时,她将获得第一个分数
}
for(int i=0;i=rankAry[curRank-1]){
if(curRank==1 | | alice[i]
您的算法中有几个错误

错误的映射 您的
rankAry
必须将排名(索引)映射到分数。然而,这一行
rankAry[0]=分数[0],最高分数映射到
0
,但最高可能的排名是
1
,而不是
0
。因此,将其更改为:

rankAry[1] = scores[0];
错误的初始排名 由于某些原因,您的
curRank
设置为
1
,如下所示:

int curRank = 1; //initialize
但是,这是错误的,因为您的
alice[0]
小于
分数[0]
,因为在方法的开头运行了以下块:

if (scores.Length == 0 || alice[0] >= scores[0]) { //degenerate cases
    for (int i = 0; i < alice.Length; ++i) {
        res[i] = 1;
    }
    return res;
}
然后,您还可以删除
curRank++
,因为您的
curRank
具有以下正确的初始值:

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++; // it's not longer needed so remove it
}
改进“非退化案件”处理 <>你的<代码>破解< /代码>条件应考虑<代码> Rangkale/Cult>在代码> Currang-1 ,而不是<代码> Currang-2 < /Cord>,因为它足以检查相邻的秩值。另外,
curRank-2
上的值对于某些输入会产生错误的结果,但我不会具体解释哪种情况,我将让您自己来确定

固定代码 因此,我根据上面的评论修复了您的方法,并通过了所有测试。给你

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[1] = scores[0]; //top score rank
    int curPos = 1; //start at the front and move down
    int curRank = 2; //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
    }

    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 - 1]) {
                break;
            }

            curRank--;
        }
        res[i] = curRank;
    }

    return res;
}
static int[]攀登排行榜(int[]得分,int[]爱丽丝){
int[]res=新的int[alice.Length];
如果(scores.Length==0 | | alice[0]>=scores[0]){//退化情况
为了
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[1] = scores[0]; //top score rank
    int curPos = 1; //start at the front and move down
    int curRank = 2; //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
    }

    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 - 1]) {
                break;
            }

            curRank--;
        }
        res[i] = curRank;
    }

    return res;
}