You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#中Array.IndexOf无匹配取最近项及排行榜排名计算优化问题

Hey there! Let's tackle your two C# questions one by one—both are about making array operations more efficient, so let's dive in.

问题一:C#的Array.IndexOf(Array, item)方法在无匹配项时,如何获取最接近的元素?

First off, Array.IndexOf only looks for exact matches, so it won't help you find the closest element out of the box. The approach you take depends on whether your array is sorted or not:

如果数组是有序的(推荐,效率更高)

Use binary search to find the insertion point for your target item—this gives you a starting point to compare neighboring elements. C#'s Array.BinarySearch returns the index of an exact match if found; if not, it returns -(insertionPoint) - 1, where insertionPoint is the position where the item would be inserted to keep the array sorted.

Here's a reusable method to find the closest element's index:

public static int FindClosestIndex(int[] sortedArray, int target)
{
    if (sortedArray == null || sortedArray.Length == 0)
        throw new ArgumentException("Array can't be null or empty!");

    int searchResult = Array.BinarySearch(sortedArray, target);
    if (searchResult >= 0)
        return searchResult; // Exact match found

    int insertionPoint = ~searchResult; // Convert negative result to insertion position

    // Handle edge cases: target is smaller than all elements or larger than all
    if (insertionPoint == 0)
        return 0;
    if (insertionPoint == sortedArray.Length)
        return sortedArray.Length - 1;

    // Compare which neighboring element is closer
    int diffBefore = target - sortedArray[insertionPoint - 1];
    int diffAfter = sortedArray[insertionPoint] - target;

    return diffBefore <= diffAfter ? insertionPoint - 1 : insertionPoint;
}

如果数组是无序的

You'll have to iterate through the entire array to track the element with the smallest absolute difference from your target. This is O(n) time, which isn't great for large arrays—if possible, sort the array first (O(n log n)) then use the binary search method above.

问题二:优化climbingLeaderboard的排名计算

Your original for-loop approach is slow because it's O(n*m) time (n = number of scores, m = number of player scores). The fix is to use binary search on the sorted, deduplicated scores array, which drops each player's score lookup to O(log n) time.

Since your scores are already in descending order (and you've deduplicated them), we can implement a custom binary search tailored to descending sorted arrays to calculate ranks directly:

Step 1: Deduplicate the original scores (if you haven't already)

Since the input is already sorted descending, we can just iterate once to remove duplicates:

List<int> uniqueScores = new List<int>();
foreach (int score in scores)
{
    if (uniqueScores.Count == 0 || uniqueScores.Last() != score)
    {
        uniqueScores.Add(score);
    }
}
int[] sortedDescUnique = uniqueScores.ToArray();

Step 2: Binary search for each player's rank

This method finds the rank of a player's score in the descending, deduplicated array:

private static int GetPlayerRank(int[] sortedDescScores, int playerScore)
{
    int left = 0;
    int right = sortedDescScores.Length - 1;

    while (left <= right)
    {
        int mid = left + (right - left) / 2; // Avoid overflow

        if (sortedDescScores[mid] == playerScore)
        {
            return mid + 1; // Rank is 1-based index
        }
        else if (sortedDescScores[mid] > playerScore)
        {
            // Target is smaller than mid, look right
            left = mid + 1;
        }
        else
        {
            // Target is larger than mid, look left
            right = mid - 1;
        }
    }

    // If no match, left is the insertion position—rank is left + 1 (1-based)
    return left + 1;
}

Step 3: Put it all together in the climbingLeaderboard method

static int[] climbingLeaderboard(int[] scores, int[] playerScores)
{
    // Deduplicate scores first
    List<int> uniqueScores = new List<int>();
    foreach (int score in scores)
    {
        if (uniqueScores.Count == 0 || uniqueScores.Last() != score)
        {
            uniqueScores.Add(score);
        }
    }
    int[] sortedDescUnique = uniqueScores.ToArray();

    int[] ranks = new int[playerScores.Length];
    for (int i = 0; i < playerScores.Length; i++)
    {
        ranks[i] = GetPlayerRank(sortedDescUnique, playerScores[i]);
    }

    return ranks;
}

Why this works better

  • Total time complexity is O(n + m log n) (n for deduplication, m log n for all player lookups) vs. O(n*m) for the original for-loop. This is a massive improvement when dealing with large datasets.
  • Array.IndexOf isn't useful here because it's a linear search (slow for big arrays) and only returns -1 when no match is found—no built-in way to get rank from that.

内容的提问来源于stack exchange,提问作者Mohamed

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 08:46:05