游戏排名第三大分数
问题描述
小M想要通过查看往届游戏比赛的排名来确定自己比赛的目标分数。他希望找到往届比赛中排名第三的分数,作为自己的目标。具体规则如下:
- 如果分数中有三个或以上不同的分数,返回其中第三大的分数。
- 如果不同的分数只有两个或更少,那么小M将选择最大的分数作为他的目标。
请你帮小M根据给定的分数数组计算目标分数。
测试样例
样例1
输入:n = 3,nums = [3, 2, 1]
输出:1
样例2
输入:n = 2,nums = [1, 2]
输出:2
样例3
输入:n = 4,nums = [2, 2, 3, 1]
输出:1
算法设计
-
对输入的分数数组进行排序。
-
遍历排序后的数组,统计不同分数的数量。
注:三个或三个以上的分数要将相同分数合并,如测试用例4输入:n = 3,nums = [15, 12, 15] 输出:15
-
根据不同分数的数量返回相应的结果:
- 如果有三个或以上的不同分数,则返回第三个最大值。
- 否则,返回最大值。
复杂度
排序
- 时间复杂度:排序操作的时间复杂度是 𝑂(𝑛log𝑛),其中 𝑛 是数组的长度。
- 空间复杂度:如果使用的是原地排序算法(如快速排序),空间复杂度为 𝑂(1);如果使用的是非原地排序算法(如归并排序),空间复杂度为 𝑂(𝑛)。 去重
- 时间复杂度:遍历排序后的数组的时间复杂度是 𝑂(𝑛)。
- 空间复杂度:如果使用额外的数组来存储不同的分数,空间复杂度为 𝑂(𝑛);如果直接在原数组上进行操作,空间复杂度为 𝑂(1) 总体时间复杂度 排序:𝑂(𝑛log𝑛) 去重:𝑂(𝑛) 总体时间复杂度为 𝑂(𝑛log𝑛)
代码
package main
import (
"fmt"
)
func solution(n int, nums []int) int {
length := len(nums)
for i := 1; i < length; i++ {
for j := i; j > 0; j-- {
if nums[j-1] < nums[j] {
nums[j-1], nums[j] = nums[j], nums[j-1]
}
}
}
count := 1
for i := 1; i < length; i++ {
if nums[i] != nums[i-1] {
count++
}
if count == 3 {
return nums[i]
}
}
return nums[0]
}
测试
func main() {
fmt.Println(solution(3, []int{3, 2, 1}) == 1)
fmt.Println(solution(2, []int{1, 2}) == 2)
fmt.Println(solution(4, []int{2, 2, 3, 1}) == 1)
}
优化
虽然插入排序在小规模数据集上表现良好,但对于大规模数据集,其 O(n^2) 的时间复杂度可能会导致性能问题。可以考虑使用更高效的排序算法,如快速排序、归并排序等,这些算法的时间复杂度为 O(n log n)。
优化后的代码
package main
import (
"fmt"
"sort"
)
func findThirdLargestScore(n int, nums []int) int {
// 使用快速排序对数组进行降序排序
sort.Slice(nums, func(i, j int) bool {
return nums[i] > nums[j]
})
count := 1
for i := 1; i < len(nums); i++ {
if nums[i] != nums[i-1] {
count++
}
if count == 3 {
return nums[i]
}
}
return nums[0]
}
func main() {
fmt.Println(findThirdLargestScore(3, []int{3, 2, 1}))
fmt.Println(findThirdLargestScore(2, []int{1, 2}))
fmt.Println(findThirdLargestScore(4, []int{2, 2, 3, 1}))
}
优化后的时间复杂度
- 排序:使用快速排序的时间复杂度为 O(n log n)。
- 去重计数:遍历排序后的数组的时间复杂度为 O(n)。
总体时间复杂度为 O(n log n)。
优化后的空间复杂度
- 快速排序:快速排序的空间复杂度为 O(log n)(递归栈空间)。
- 其他变量:只使用了常数级别的额外空间,空间复杂度为 O(1)。
总体空间复杂度为 O(log n)。