订阅更新

相邻同学换座位:奇偶编号互换

SQL 实战 123 题 · 第 45 题 中等 约 2 分钟读完

LeetCode 626 · CASE、LAG/LEAD、奇偶判断

本文目录
  1. 面试怎么回答
  2. 题意
  3. 表结构
  4. 思路
  5. 参考解法
  6. 易错点

面试怎么回答

我最常用的是改 id:偶数 id 减 1,奇数 id 加 1,但如果奇数 id 等于总人数就保持不变,最后 ORDER BY 新 id。用 LAG/LEAD 交换学生名也行,关键都是处理好人数为奇数时最后一个人。

先把这段讲顺;面试官追问时,再展开下面的原理和细节。

详细讲解

题意

座位表的 id 连续递增,每个 id 对应一个学生。把相邻两个学生的座位互换(1 和 2 换、3 和 4 换……),如果总人数是奇数,最后一个人不动。按 id 输出新的座位安排。

表结构

  • seat:id(主键,连续递增)、student

思路

有两种思路:一是改学生,偶数 id 取上一行的学生、奇数 id 取下一行的学生(最后一个奇数 id 没有下一行就保持不变),用 LAG/LEAD 实现;二是改 id,偶数 id 减 1、奇数 id 加 1,最后一个奇数 id 不变,再按新 id 排序。

参考解法

写法 1:用 LAG / LEAD 交换学生

select id,
(case when id%2=0 then f
      when id%2=1 && b is not null then b
      else student end) student
from(
    select id,student,
    lag(student,1,null) over(order by id) f,
    lead(student,1,null) over(order by id) b
    from seat
)t1

写法 2:直接改 id,再按新 id 排序

select 
    if(id%2=0,
        id-1,
        if(id=(select count(distinct id) from seat),
            id,
            id+1)) 
    as id,student 
from seat 
order by id;

写法 3:异或技巧:(id-1) XOR 1 + 1 正好把 1↔2、3↔4 配对

select b.id,a.student from 
seat as a,seat as b,(select count(*) as cnt from seat) as c 
where b.id=1^(a.id-1)+1
-- where a.id=1^(b.id-1)+1; 也可以这样写,更容易理解
 || (c.cnt%2 && b.id=c.cnt && a.id=c.cnt);

易错点

  • 忘了处理奇数人数时的最后一位,会把他换成 NULL 或换出表外。
  • 第一种写法中 && 是 MySQL 语法,标准写法用 AND。
刷题进度保存在当前浏览器