携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第15天,换座位[异或巧妙的让奇偶互换] - 掘金 (juejin.cn)
前言
将奇数id和偶数id的其他字段交换,同时考察转换问题能力 & 直接分析能力。如 换其他字段 和 换id是镜像对称的,换了其他字段就等同于换了id。
一、换座位
二、直接法 & 转换法 + 巧妙异或
1、直接法
# 直接法,联表。
with view4base as(
select s1.id,s1.student,s2.student next
from Seat s1 left join Seat s2 on s1.id & 1 = 1 and s1.id + 1 = s2.id or s1.id & 1 = 0 and s1.id - 1 = s2.id
)
select
id,
if(next is null,student,next) student
from view4base
# 直接法,联表改进。
with view4base as(
select s1.id,s1.student,s2.student next
from Seat s1 left join Seat s2 on (s1.id + 1) ^ 1 - 1 = s2.id # 让奇数先加一再加一,让偶数先加一再减一 一直不变,两者减一即可。
)
select
id,
if(next is null,student,next) student
from view4base
2、转换法
# 问题转换法,把它们id换了再排序。
select
case
when total & 1 = 1 and id = total then id
when id & 1 = 1 then id + 1
when true then id - 1
end id,
student
from Seat,(select max(id) total from Seat) t # 巧用笛卡儿积,而不是窗口函数。
order by id
# 问题转换法,巧妙的奇偶交换。
select
if(total & 1 = 1 and total = id,id,(id + 1) ^ 1 - 1) id,
student
from Seat,(select max(id) total from Seat) t # 巧用笛卡儿积,而不是窗口函数。
order by id
总结
1)巧妙的异或位运算,让奇偶数互换。
2)多锻炼问题转换的能力,如换id 和 换其他字段,是镜像对称的,换了id不就等同于换了其他大把字段,像是四两拨千斤的感觉。又比如筛选记录时,筛选了外键即另一张表的主键,就筛选除了特定信息,不一定要联表来做。
参考文献
[1] LeetCode 换座位