【问题标题】:Optimizing the following hackerrank program优化以下hackerrank程序
【发布时间】:2018-03-12 18:14:24
【问题描述】:

我想优化我制作的以下代码,以便它通过hackerrank问题中的所有测试用例。它目前有效,但由于超时而在某些情况下失败。你能指导我如何在不改变概念的情况下优化代码吗?

问题

Alice 正在玩街机游戏,并想爬到排行榜的顶端。 当她通过每个级别时,你能帮助她跟踪她的排名吗?游戏使用密集排名,所以它的排行榜是这样工作的:

• 得分最高的玩家在排行榜上排名第一。

• 得分相同的玩家获得相同的排名编号,下一位玩家获得紧随其后的排名编号。

例如,四个玩家的分数分别为 100、90、90 和 80。这些玩家的排名分别为 1、2、2 和 3。

当 Alice 开始玩游戏时,排行榜上已经有 n 人。 Alice 玩m 级别,我们表示她通过每个级别后的总分。完成每个级别后,Alice 想知道她当前的排名。

您将获得一组单调递减的排行榜分数,以及另一组 Alice 在每个级别的游戏中的累积分数。必须打印整数:整数应该表示 Alice 通过每一级后的当前等级。

输入格式:

  • 第一行包含一个整数n,表示已经在排行榜上的玩家数量。
  • 下一行包含n 用空格分隔的整数,描述它们各自的得分值。
  • 下一行包含一个整数m,表示Alice 击败的级别数。
  • 最后一行包含m 以空格分隔的整数,描述每个玩家的各自值。

输出格式:

打印整数。整数应该表示 Alice 通过每一关后的排名。

输入

7
100 100 50 40 40 20 10
4
5 25 50 120

输出

6
4
2
1

这是我的代码:

#include <math.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

struct player {
    int rank;
    int score;
};

struct node {
    struct player data;
    struct node *next;
};

int main() {
    int n, i, m, temp, count = 1, x;
    struct node *ptr, *head;
    head = (struct node *)malloc(sizeof(struct node));
    ptr = head;
    scanf("%d", &n);
    for (i = 0; i < n; i++) {
        scanf("%d", &x);
        ptr->data.score = x;
        if (x < temp)
            count++;
        ptr->data.rank = count;
        temp = ptr->data.score;
        ptr->next = (struct node *)malloc(sizeof(struct node));
        ptr = ptr->next;
    }
    ptr = NULL;
    ptr = head;
    scanf("%d", &m);
    for (i = 0; i < m; i++) {
        scanf(" %d", &x);
        while (x < ptr->data.score)
            ptr = ptr->next;
        if (ptr->next == NULL)
            ptr->data.rank = count + 1;
        printf("%d\n", ptr->data.rank);
        ptr = head;
    }
    return 0;
}

问题在于,每次我为 Alice 取出排名时,我都是从头开始遍历链表。对此有什么可能的优化?

【问题讨论】:

  • 这类问题的重点不一定只是为了写出高效的代码,而是要找到一个聪明的算法。 是你必须解决的真正挑战。
  • 我知道。我试过了,但我无法使用链接列表来解决我的问题。所以,如果你能帮我一点忙,那就太好了。 :) 可以通过使用堆栈来解决问题,但我只想使用链表。
  • 残酷 - 如果你不能解决它,尝试另一个挑战。该站点不是解决我的挑战的站点,而是针对 C 的特定问题。
  • 我会继续尝试其他挑战,但这并不是我在 stackoverflow 上发帖的真正目的,是吗?
  • 我的回答是,如果我能解决问题,我会直接提交给 Hackerrank,而不是给你。如果我不能解决它,我会把问题放在一边,稍后再回来。

标签: c algorithm data-structures linked-list


【解决方案1】:

您的代码中存在未定义的行为,因为您没有初始化 temp 变量:第一次比较 if (x &lt; temp) 具有未定义的行为,因此 count 可能会错误地递增。

Paul 的方法是将复杂度从 O(N2) 降低到 O(N) 的非常好的解决方案。

这里是修改后的代码:

#include <stdio.h>
#include <stdlib.h>

struct node {
    int rank;
    int score;
    struct node *next;
};

int main(void) {
    int n, i, m, last = 0, rank = 1, x;
    struct node *ptr, *head = NULL;
    if (scanf("%d", &n) != 1)
        return 1;
    for (i = 0; i < n; i++) {
        ptr = malloc(sizeof(*ptr));
        if (ptr == NULL)
            return 1;
        if (scanf("%d", &ptr->score) != 1)
            return 1;
        if (ptr->score < last)
            rank++;
        ptr->rank = rank;
        last = ptr->score;
        ptr->next = head;
        head = ptr;
    }
    if (scanf("%d", &m) != 1)
        return 1;
    for (ptr = head, i = 0; i < m; i++) {
        if (scanf(" %d", &x) != 1)
            return 1;
        while (ptr && x > ptr->score)
            ptr = ptr->next;
        if (ptr == NULL)
            rank = 1;
        else
        if (x == ptr->score)
            rank = ptr->rank;
        else
            rank = ptr->rank + 1;
        printf("%d\n", rank);
    }
    return 0;
}

【讨论】:

  • 谢谢。代码现在更好更高效了。
【解决方案2】:

反转代表排行榜的列表,使排行榜单调递增。如果排行榜是这样排序的,你只需要从最后一个位置开始遍历排行榜。 IE。对于您的示例输入:

10/5    20/4    40/3    40/3     50/2     100/1     100/1           leaderboard
5               25               50                           120   score
6               4                2                            1     pos

作为伪代码:

node n = leaderboard.reverse().head

foreach score in scorelist:
    while n != null and n.score > score
        n = n.next

    if n == null:
        print 1
    else:
        print n.pos - 1

这是因为根据score[i] 在排行榜中的位置 (l[j]),我们知道score[i + 1] 必须在位置l[j + x],其中x &gt; 0 在反向排行榜中。

【讨论】:

  • 知道了。谢谢你。我看到,效率受到很大影响。
  • @Adirtha 很高兴我能帮上忙 :)。如果它解决了您的问题,请不要忘记accept 答案;)。欢迎来到 SO
猜你喜欢
  • 2015-11-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多