红包运气排行榜
题目内容
解题思路
1.处理重复的参与者
- 要注意处理重复出现的参与抢红包的人,把他们的所抢红包金额加起来,可以使用一个对象(amounts)来存储每个参与者的累计金额。
- 遍历参与者列表 ‘s’,如果某个名字已经在出现过,就将该参与者的金额累加;如果还没有出现过,则初始化这个名字的金额。
2.记录每个参与者的首次出现顺序
- 为了在金额相同的情况下按首次出现的顺序排序,可以使用另一个对象(order)来记录每个参与者名字第一次出现的位置。
- 在遍历过程中,如果某个参与者是第一次出现,就将该参与者的顺序位置存入order。
3.排序
- 将amounts中的键(参与者名字)转换为数组。
- 排序规则:
- 金额大的参与者排在前面,因此在比较函数中
amounts[b] - amounts[a]。 - 如果金额相同,则按 order 中记录的顺序升序排列,即
order[a] - order[b]。
- 金额大的参与者排在前面,因此在比较函数中
4.最后返回排序后的名字列表
function solution(n, s, x) {
// 用对象来累计每个参与者的总金额,并记录首次出现的顺序
const amounts = {};
const order = {};
for (let i = 0; i < n; i++) {
const name = s[i];
const amount = x[i];
if (amounts.hasOwnProperty(name)) {
amounts[name] += amount;
} else {
amounts[name] = amount;
order[name] = i; // 记录该参与者的首次出现位置
}
}
// 将对象转换为数组,以便进行排序
const sortedParticipants = Object.keys(amounts).sort((a, b) => {
// 先按金额降序排列
if (amounts[b] !== amounts[a]) {
return amounts[b] - amounts[a];
}
// 金额相同时按首次出现顺序升序排列
return order[a] - order[b];
});
return sortedParticipants;
}
代码分析
时间复杂度
O(n log n),主要花费在排序上,排序操作是 O(n log n),遍历和累加操作是 O(n)。
空间复杂度
O(n),amounts 和 order 各存储 n 个元素的键值对。
优点
-
时间复杂度较优:
- 主要操作集中在排序,时间复杂度为 O(n log n),符合常见排序算法的复杂度。在数据量较大的情况下,这种复杂度表现依然较好。
-
空间分离处理:
- 通过amounts和 order两个对象分离存储金额和顺序,使得代码清晰且逻辑紧凑,便于理解和调试。
不足
- 缺乏通用性
- 这段代码是专门用来处理金额降序和首次顺序升序的需求。如果排序规则改变(比如需要金额升序或其他排序方式),则需要重新编写排序规则,所以说灵活性不够高。
- 增加内存的占用
- 使用 amounts 和 order 两个对象来记录金额和顺序,对于大数据集会增加额外的内存占用。
总结
这段代码通过对象和排序的结合,实现了对抢红包结果的排名,逻辑清晰且有效满足了题目的多重排序需求。其优点在于结构紧凑,时间复杂度合理。然而,代码在通用性和鲁棒性方面仍有提升空间,特别是在处理大规模数据和异常输入方面。此外,添加更系统的测试方案可提高代码的可靠性。总体而言,这段代码展示了将数据处理与排序规则结合应用的技巧,为解决类似的排序问题提供了良好的思路。