C#如何实现含重复值的数组元素排名?支持同名次与跳位规则
带重复值的C#数组竞争排名实现
核心规则对齐
实现的排名逻辑完全匹配需求约束,即竞争排名(1224式排名):
- 数组元素数值越大,排名越靠前,名次从1开始计数
- 相同数值的元素共享完全相同的排名
- 重复值会占用对应位次,导致后续元素的排名不连续——即并列第n名后,下一个名次为n加并列元素的总数量,而非n+1
核心实现逻辑等价于:单个元素的排名 = 数组中严格大于当前元素的元素总数 + 1
规则匹配验证:
- 输入
[650,150,150,200],计算得到排名[1,3,3,2],与需求一致 - 输入
[650,150,150,200,100],100对应的严格大于它的元素共4个,排名为5,完全符合“不使用连续稠密排名、输出5而非4”的要求 - 输入
[650,200,200,150],按规则计算得到排名[1,2,2,4]。需求示例中提到的输出[1,2,2,3]属于连续稠密排名结果,与后续补充的跳位规则存在差异,实际实现以补充的跳位规则为准。
具体代码实现
极简LINQ版本(适合小数据量,代码最精简)
不需要复杂逻辑,直接遍历每个元素统计比它大的元素数量即可:
public static int[] GetCompetitionRanks(int[] input) { return input .Select(current => input.Count(item => item > current) + 1) .ToArray(); }
高性能版本(适合大数组,低时间复杂度)
当数组长度较大时,通过排序+字典缓存的方式,把时间复杂度从O(n²)降到O(nlogn),减少重复计算:
public static int[] GetCompetitionRanksFast(int[] input) { // 数组按降序排序 var sortedDesc = input.OrderByDescending(v => v).ToArray(); var rankMap = new Dictionary<int, int>(); // 遍历排序后的数组,记录每个值第一次出现的位置,位置+1即为对应排名 for (int idx = 0; idx < sortedDesc.Length; idx++) { int val = sortedDesc[idx]; if (!rankMap.ContainsKey(val)) { rankMap[val] = idx + 1; } } // 按原数组顺序匹配返回排名 return input.Select(v => rankMap[v]).ToArray(); }
结果验证
将测试用例代入实现方法,输出结果完全匹配竞争排名要求:
- 输入
[650,150,150,200]→ 输出[1,3,3,2] - 输入
[650,150,150,200,100]→ 输出[1,3,3,2,5] - 输入
[650,200,200,150]→ 输出[1,2,2,4]
内容的提问来源于stack exchange,提问作者Deepak Kothari
相关产品推荐
相关产品推荐

