techiall / Blog

🍋 [My Blog] See discussions
https://github.com/techiall/Blog/discussions
MIT License
8 stars 1 forks source link

Leetcode | 分数排名 #13

Open techiall opened 6 years ago

techiall commented 6 years ago

编写一个 SQL 查询来实现分数排名。如果两个分数相同,则两个分数排名(Rank)相同。请注意,平分后的下一个名次应该是下一个连续的整数值。换句话说,名次之间不应该有“间隔”。

+----+-------+
| Id | Score |
+----+-------+
| 1  | 3.50  |
| 2  | 3.65  |
| 3  | 4.00  |
| 4  | 3.85  |
| 5  | 4.00  |
| 6  | 3.65  |
+----+-------+

例如,根据上述给定的 Scores 表,你的查询应该返回(按分数从高到低排列):

+-------+------+
| Score | Rank |
+-------+------+
| 4.00  | 1    |
| 4.00  | 1    |
| 3.85  | 2    |
| 3.65  | 3    |
| 3.65  | 3    |
| 3.50  | 4    |
+-------+------+

原先的想法使用 SQL 里面的变量来做的,然后点执行代码的时候发现过不去,就放弃了这种想法。

使用 count 计数, distinct 去重,比较两个分数,在利用 order by 进行排序即可。

mysql

select s.Score, (select count(distinct s1.Score)

    from Scores s1 where s1.Score >= s.Score) Rank

from Scores s order by s.Score desc;

测试成功后,发现用的时间有点长……

我看了一下其他人的提交,找了执行用时较少的代码看,居然发现他们是使用变量,而且思路更简单。

(其实执行代码那里使用变量测试不通过,但是直接提交一发,就知道是不是正确了。

思路如下

预选设置一个分数,实际生活中是不存在负的分数的,因此选一个负数的值作为预置的分数即可。

rank 的起始为 0,递增即可。

rank 递增的条件:等于上一次的 rank,加上判断分数是否等于上一次的分数。

比较的两个值不相等就是 1,就递增,如果相等,就不递增。

@cur_rank := @cur_rank + (@pre_score != (@pre_score := s.Score))

相当于

@tmp1 = (@pre_score := s.Score);

@tmp2 = @pre_score != tmp; // 值只会是 0 或者 1

@cur_rank = @cur_rank + tmp2;
set @pre_score = -324234;

set @cur_rank = 0;

select s.Score, (@cur_rank := @cur_rank + (@pre_score != (@pre_score := s.Score))) Rank

    from Scores s order by 1 desc;