Hackerrank:攀登排行榜

时间:2019-05-24 22:06:28

标签: c#

我与hackerrank algorithm problem有交易。

除6-7-8-9以外,它在所有情况下均有效。它给出超时错误。我在这个级别花费了很多时间。有人看到问题出在哪里?

static long[] climbingLeaderboard(long[] scores, long[] alice)  
{
    //long[] ranks = new long[scores.Length];
    long[] aliceRanks = new long[alice.Length]; // same length with alice length
    long lastPoint = 0;
    long lastRank;
    for (long i = 0; i < alice.Length; i++)
    {
        lastPoint = scores[0];
        lastRank = 1;
        bool isIn = false; // if never drop in if statement 
        for (long j = 0; j < scores.Length; j++)
        {
            if (lastPoint != scores[j])  //if score is not same, raise the variable
            {
                lastPoint = scores[j];
                lastRank++;
            }

            if (alice[i] >= scores[j])
            {
                aliceRanks[i] = lastRank;
                isIn = true;
                break;
            }
            aliceRanks[i] = !isIn & j + 1 == scores.Length ? ++lastRank : aliceRanks[i]; //drop in here
        }
    }
    return aliceRanks;
}

7 个答案:

答案 0 :(得分:0)

我很无聊,所以我与 Linq 进行了尝试,并为您大力评论

给予

public static IEnumerable<int> GetRanks(long[] scores, long[] person)

   // Convert scores to a tuple
   => scores.Select(s => (scores: s, isPerson: false))

             // convert persons score to a tuple and concat
            .Concat(person.Select(s => (scores: s, isPerson: true)))

             // Group by scores
            .GroupBy(x => x.scores)

             // order by score
            .OrderBy(x => x.Key)

             // select into an indexable tuple so we know everyones rank
            .Select((groups, i) => (rank: i, groups))

             // Filter the person
            .Where(x => x.groups.Any(y => y.isPerson))

             // select the rank
            .Select(x => x.rank);

用法

static void Main(string[] args)
{
   var scores = new long[]{1, 34, 565, 43, 44, 56, 67};   
   var alice = new long[]{578, 40, 50, 67, 6};

   var ranks = GetRanks(scores, alice);

   foreach (var rank in ranks)
      Console.WriteLine(rank);

}

输出

1
3
6
8
10

答案 1 :(得分:0)

这是一种利用BinarySearch的解决方案。此方法返回数组中搜索到的数字的索引,或者,如果找不到该数字,则返回一个负数,该负数是数组中下一个元素的索引的按位补码。二进制搜索仅适用于排序的数组。

public static int[] GetRanks(long[] scores, long[] person)
{
    var defaultComparer = Comparer<long>.Default;
    var reverseComparer = Comparer<long>.Create((x, y) => -defaultComparer.Compare(x, y));
    var distinctOrderedScores = scores.Distinct().OrderBy(i => i, reverseComparer).ToArray();
    return person
        .Select(i => Array.BinarySearch(distinctOrderedScores, i, reverseComparer))
        .Select(pos => (pos >= 0 ? pos : ~pos) + 1)
        .ToArray();
}

用法示例:

var scores = new long[] { 100, 100, 50, 40, 40, 20, 10 };
var alice = new long[] { 5, 25, 50, 120 };
var ranks = GetRanks(scores, alice);
Console.WriteLine($"Ranks: {String.Join(", ", ranks)}");

输出:

  

排名:6、4、2、1

答案 2 :(得分:0)

基于给定的约束,蛮力解决方案对于该问题将无效。 您必须优化代码,这里的关键部分是查找可以通过使用二进制搜索有效完成的确切位置。

以下是使用二进制搜索的解决方案:-

static int[] climbingLeaderboard(int[] scores, int[] alice) {
        int n = scores.length;
        int m = alice.length;

        int res[] = new int[m];
        int[] rank = new int[n];

        rank[0] = 1;

        for (int i = 1; i < n; i++) {
            if (scores[i] == scores[i - 1]) {
                rank[i] = rank[i - 1];
            } else {
                rank[i] = rank[i - 1] + 1;
            }
        }

        for (int i = 0; i < m; i++) {
            int aliceScore = alice[i];
            if (aliceScore > scores[0]) {
                res[i] = 1;
            } else if (aliceScore < scores[n - 1]) {
                res[i] = rank[n - 1] + 1;
            } else {
                int index = binarySearch(scores, aliceScore);
                res[i] = rank[index];

            }
        }
        return res;

    }

    private static int binarySearch(int[] a, int key) {

        int lo = 0;
        int hi = a.length - 1;

        while (lo <= hi) {
            int mid = lo + (hi - lo) / 2;
            if (a[mid] == key) {
                return mid;
            } else if (a[mid] < key && key < a[mid - 1]) {
                return mid;
            } else if (a[mid] > key && key >= a[mid + 1]) {
                return mid + 1;
            } else if (a[mid] < key) {
                hi = mid - 1;
            } else if (a[mid] > key) {
                lo = mid + 1;
            }
        }
        return -1;
    }

您可以参考此 link 以获得更详细的视频说明。

答案 3 :(得分:0)

此问题可以在 O(n)时间内解决,根本不需要二进制搜索。首先,我们需要提取问题陈述中给出的最有用的数据,即

  

现有排行榜 得分 按降序排列。

     

爱丽丝的得分 ,按升序排列。

一种使之有用的方法是创建两个指针,一个指针位于 alice 数组的开始,我们称之为“ i ”,第二个是 分数 数组的末尾,我们称其为“ j ”。然后循环,直到 i 到达 alice 数组的末尾,并且在每次迭代中,我们检查三个主要条件。如果 alice [i] 小于 分数[j],我们将 i 递增1。 ] ,因为 alice 的下一个元素也可能小于 分数 < / strong>,或者如果 alice [i] 大于 ,则我们递减 j 得分[j] ,因为我们确定 的下一个元素也大于 得分 。最后一个条件是,如果 alice [i] ==得分[j] ,我们只会增加 i

我用C ++解决了这个问题,我的目的是让您理解算法,如果您理解它,我认为您可以轻松地将其转换为C#。如有任何疑问,请告诉我。这是代码:

// Complete the climbingLeaderboard function below.
vector<int> climbingLeaderboard(vector<int> scores, vector<int> alice) {
    int j = 1, i = 1;
    // this is to remove duplicates from the scores vector
    for(i =1; i < scores.size(); i++){
        if(scores[i] != scores[i-1]){
            scores[j++] = scores[i];
        }
    }
    int size = scores.size();
    for(i = 0; i < size-j; i++){
        scores.pop_back();
    }
    vector<int> ranks;

    i = 0;
    j = scores.size()-1;
    while(i < alice.size()){
        if(j < 0){
            ranks.push_back(1);
            i++;
            continue;
        }
        if(alice[i] < scores[j]){
            ranks.push_back(j+2);
            i++;
        } else if(alice[i] > scores[j]){
            j--;
        } else {
            ranks.push_back(j+1);
            i++;
        }
    }

    return ranks;
}

我认为这也可能对您有帮助:

  

vector 就像一个会自动调整大小的数组列表。

     

push_back() 将插入到向量的末尾。

     

pop_back() 正在从向量的结尾删除。

答案 4 :(得分:0)

static int[] climbingLeaderboard(int[] scores, int[] alice) {

      int[] uniqueScores = IntStream.of(scores).distinct().toArray();

        int [] rank = new int [alice.length];

        int startIndex=0;

        for(int j=alice.length-1; j>=0;j--) {


        for(int i=startIndex; i<=uniqueScores.length-1;i++) {

            if (alice[j]<uniqueScores[uniqueScores.length-1]){
                    rank[j]=uniqueScores.length+1;
                    break;
                }

            else if(alice[j]>=uniqueScores[i]) {
                    rank[j]=i+1;
                    startIndex=i;
                    break;
                }

                else{continue;}

            }
    } 
    return rank;
    }

答案 5 :(得分:0)

我在 javascript 中解决排行榜 Hackerrank 问题的解决方案。问题的时间复杂度可以是 O(i+j),i 是分数的长度,j 是 alice 的长度。空间复杂度为 O(1)。

// Complete the climbingLeaderboard function below.
function climbingLeaderboard(scores, alice) {
    const ans = [];
    let count = 0;
    // the alice array is arranged in ascending order
    let j = alice.length - 1;
    for (let i = 0 ; i < scores.length ; i++) {
        const score = scores[i];
        for (; j >= 0 ; j--) {
            if (alice[j] >= score) {
                // if higher than score
                ans.unshift(count+1);
            } else if (i === scores.length - 1) {
                // if smallest
                ans.unshift(count+2);
            } else {
                break;
            }
        }
        
        // actual rank of the score in leaderboard
        if (score !== scores[i-1]) {
            count++;
        }
    }
    return ans;
}

答案 6 :(得分:-1)

我在Java中解决排行榜Hackerrank问题的解决方案。

    // Complete the climbingLeaderboard function below.
static int[] climbingLeaderboard(int[] scores, int[] alice) {
  Arrays.sort(scores);
  HashSet<Integer> set = new HashSet<Integer>();
int[] ar = new int[alice.length];
int sc = 0;


  for(int i=0; i<alice.length; i++){
    sc = 1;
    set.clear();
    for(int j=0; j<scores.length; j++){
       if(alice[i] < scores[j] && !set.contains(scores[j])){
          sc++;
          set.add(scores[j]);
        }
    }
    ar[i] = sc;
  }return ar;

}