The problem is to create an array of player ranks based on 2 other arrays: leaderboard and player scores. More explanations of the problem here: https://www.hackerrank.com/challenges/climbing-the-leaderboard/problem.
The code below is a spaghetti but it's working fine. But, for large size of ranked array(200000 elements for example), it times out. I'm not asking for code to copy/paste. I just wanna know if there is a way to optimize this code.
int* climbingLeaderboard(int ranked_count, int* ranked, int player_count, int* player, int* result_count) {
*result_count=player_count;
// remove duplicates
int removed=0;
for(int i=0, j=1; i<ranked_count-removed; i , j ){
if(ranked[i]==ranked[j]){
for(int k=j; k<ranked_count-removed; k )
ranked[k]=ranked[k 1];
removed ;
}
}
int newsize=ranked_count-removed;
// create an array to store ranks then fill it
int* positions=malloc(newsize*sizeof(int));
positions[0]=1;
for(int i=0, j=1; j<newsize; i , j ){
positions[j]=(ranked[j]<ranked[i])? (positions[i] 1) : positions[i];
}
// create and fill the results array using binary search
int* res = malloc(player_count*sizeof(int));
int start=0, end=newsize-1, middle=(start end)/2;
int j, k=newsize-1;
for(int i=0; i<player_count; i ){
if(i>0&&player[i]==player[i-1]){
*(res i)=(*(res (i-1)));
continue;
}
if(player[i]>=ranked[middle]){
*(res i)=positions[middle];
j=middle-1;
while(j>=0){
if(player[i]>=ranked[j])
*(res i)=positions[j];
else if(j==k)
*(res i)=positions[j] 1;
else break;
--j;
}
start=0; end=middle-1;
}
else{
*(res i)=positions[newsize-1] 1;
j=newsize-1;
while(j>=middle){
if(player[i]>=ranked[j])
*(res i)=positions[j];
else if(j==k)
*(res i)=positions[j] 1;
else break;
--j;
}
start=middle 1; end=newsize-1;
}
middle=(start end)/2;
}
free(positions);
return res;
}
CodePudding user response:
The initial loop to remove duplicates has a potential quadratic time complexity. You can achieve linear complexity using the 2 finger approach:
int removed = 0;
for (int i = 1, j = 1; j < ranked_count; j ) {
if (ranked[i - 1] != ranked[j])
ranked[i ] = ranked[j];
else
removed ;
}
More generally, the argument arrays should not be changed in spite of the sloppy prototype given:
int *climbingLeaderboard(int ranked_count, int *ranked,
int player_count, int *player,
int *result_count);
Here are simple steps I would recommend to solve this problem:
- allocate and initialize a
rankingarray with the ranking for each of the scores in therankedarray. Be careful to allocateranked_count 1elements. - allocate a result array
resof lengthplayer_count, set theresult_counttoplayer_count. - starting with
pos = ranked_count, for each entryiinplayer:- locate the position
poswhere the entry would be inserted in therankingarray using binary search between position0and the currentposinclusive. Make sure you find the smallest entry in case of duplicate scores. - set
res[i]toranking[pos]
- locate the position
- free the
rankingarray - return the
resarray.
Here is a simple implementation:
int *climbingLeaderboard(int ranked_count, int *ranked,
int player_count, int *player,
int *result_count)
{
if (player_count <= 0) {
*result_count = 0;
return NULL;
}
int *ranking = malloc(sizeof(*ranking) * (ranked_count 1));
int rank = 1;
ranking[0] = rank;
for (int i = 1; i < ranked_count; i ) {
if (ranked[i] != ranked[i - 1])
rank ;
ranking[i] = rank;
}
ranking[ranked_count] = rank 1;
int *res = malloc(sizeof(*res) * player_count);
*result_count = player_count;
int pos = ranked_count;
for (int i = 0; i < player_count; i ) {
int start = 0;
while (start < pos) {
int middle = start (pos - start) / 2;
if (ranked[middle] > player[i])
start = middle 1;
else
pos = middle;
}
res[i] = ranking[pos];
}
free(ranking);
return res;
}
CodePudding user response:
Look for ways to use "branchless" to improve execution speed:
positions[0]=1;
for(int i=0, j=1; j<newsize; i , j ){
positions[j]=(ranked[j]<ranked[i])? (positions[i] 1) : positions[i];
}
becomes
positions[0] = 1;
for( int i = 0, j = 1; j < newsize; i , j )
positions[j] = positions[i] (ranked[j] < ranked[i]);
Other than this, I don't even want to try to sort out what this code is attempting.
