我想优化以下代码,以便在hackerrank问题中传递所有测试用例。它目前有效但由于超时而导致某些情况失败。您能否指导我如何在不改变概念的情况下优化代码?
问题
爱丽丝正在玩街机游戏,想要爬到排行榜的顶端。 她能帮助她追踪每个级别的排名吗?游戏使用密集排名,因此其排行榜的工作方式如下:
•得分最高的玩家是排行榜上的排名。
•得分相同的玩家获得相同的排名,下一位玩家将获得紧随其后的排名。
例如,四名球员的得分分别为100分,90分,90分和80分。这些球员的得分分别为1,2,3和3。
当Alice开始播放时,排行榜上已有
n
人。 Alice为m
级别玩,我们在通过每个级别后表示她的总得分。完成每个级别后,Alice想知道她目前的等级。您将获得一系列单调递减的排行榜得分,以及每个级别的游戏的另一个Alice累积得分数组。你必须打印整数:整数应该表示通过每个级别后Alice的当前排名。
输入格式:
- 第一行包含一个整数
n
,表示排行榜上已有的玩家数量。- 下一行包含
n
以空格分隔的整数,用于描述其分数的相应值。- 下一行包含一个整数
m
,表示Alice击败的等级数。- 最后一行包含
m
以空格分隔的整数,用于描述每个玩家的各自值。输出格式:
打印整数。通过每个级别后,整数应指示Alice的等级。
INPUT
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的排名时,我都会从头开始遍历链表。对此可能有什么优化?
答案 0 :(得分:2)
反转代表排行榜的列表,使排行榜单调增加。如果以这种方式订购排行榜,您只需要从最后一个位置开始遍历排行榜。即为您的示例 - 输入:
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 > 0
在反向排行榜中。
答案 1 :(得分:0)
您的代码中存在未定义的行为,因为您未初始化temp
变量:第一个比较if (x < temp)
具有未定义的行为,因此count
可能会错误地增加。
以下是修改后的代码:
#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;
}