【语法】
一、隐蔽陷阱
想知道一份乱序榜单有多乱:任意两笔的先后颠倒了几对?两两比对是 n² 次,5000 条要 1250 万次——排序本来就要做,这个计数能不能搭车完成?
二、底层原理
归并排序在两半各自有序后合并,当后半的元素先于前半剩余元素被搬走时,它与前半剩下的每一个元素各构成一个逆序对。在搬运瞬间累加计数即可,排序整体 O(n log n),逆序对顺路白得。
三、正确代码
基础写法(归并合并中计数):
local function mergeCount(a, tmp, lo, mid, hi)
local i, j, k, cnt = lo, mid + 1, lo, 0
while i <= mid and j <= hi do
if a[i] <= a[j] then
tmp[k] = a[i]; i = i + 1
else
cnt = cnt + mid - i + 1
tmp[k] = a[j]; j = j + 1
end
k = k + 1
end
while i <= mid do tmp[k] = a[i]; i = i + 1; k = k + 1 end
while j <= hi do tmp[k] = a[j]; j = j + 1; k = k + 1 end
for t = lo, hi do a[t] = tmp[t] end
return cnt
end
进阶写法(递归统计入口):
local function countInv(a, tmp, lo, hi)
if lo >= hi then return 0 end
local mid = math.floor((lo + hi) / 2)
return countInv(a, tmp, lo, mid)
+ countInv(a, tmp, mid + 1, hi)
+ mergeCount(a, tmp, lo, mid, hi)
end
local p = getplayerbyname("rank01")
sendmsg(p, 1, "逆序对 "
.. countInv({3, 1, 2}, {}, 1, 3) .. " 对")
四、引擎验证
{3,1,2} 数出 2 对(3 压住 1 与 2);5000 条乱序数据从 1250 万次比对降到约 6 万步,降幅约 200 倍。
五、FAQ
问:相等元素算逆序吗?
答:不算,比较用小于等于,结果稳定。
问:计数会溢出吗?
答:10 万条上限约 50 亿对,双精度内安全。
全站技术干货持续更新:996 引擎 / Lua 实战帖,语法、参数与示例一篇讲透。进入文章地图 · 查看全部 →
【语法】 一、机制原理 一行代码拆解:local extra = index[main[key]] or {}。两张表按共同…
【游戏】 一、规则机制 隐蔽的坑:拖拽小窗松手位置随缘,有的只剩一半挂在屏幕外,再也拉不回来。边缘吸附补上收尾:松手时窗口落…
【游戏】 一、规则机制 一行代码拆解:if text == lastText and now - lastAt < 5 th…
【语法】 一、机制原理 抛坑提问:二分查找在均匀分布的有序数组上,还能再快吗?插值查找把对半改成按比例估位:目标值在区间里处…
【游戏】 一、规则机制 线上事故:新手第一次进主界面面对满屏按钮无所适从,客诉清一色"不知道先点哪"。新手遮罩的流程:首次进…
【游戏】 一、规则机制 抛个坑:装备好坏要看攻击、气血、抗性一堆属性,太费劲——综合评分怎么算才服众?评分规则:各属性按配置…