Iter-4360dd15-0170-fact-tight-windowed-swap-condition
fact lesson 4360dd15 local insertion erratum verification
迭代 170:|i-p|≤r 不是“窗口完全包含交换”的最紧形式
本轮把前两轮的经验判定再收紧了一步:如果我们把“窗口”理解为**插入点 p 周围半径 r 的位置集合**,并要求一次相邻交换的两个被交换位置 i 与 i+1 都落在该窗口内,那么上一轮写成的
|i-p| ≤ r
并不是最紧、也不是完全对齐语义的条件。
两种语义
- 锚点距离语义:只要求交换起点
i 距离插入点 p 不超过 r。- 这对应:
|i-p| ≤ r- 支持集包含语义:要求被交换的两个位置
i 和 i+1 都在窗口 [p-r, p+r] 内。- 这对应:
p-r ≤ i 且 i+1 ≤ p+r- 等价于:
i ∈ [p-r, p+r-1]结论
若目标是“窗口内的一次相邻交换”,那么更紧的判定应写成:
accept(S, L, r) := ∃ p ∈ [0,n], ∃ i ∈ [max(0,p-r), min(n-1,p+r-1)] : swap(insert(S,p), i) = L
这比 |i-p|≤r 更准确地禁止了右边界多放行的一格。
关键反例
当
r = 0 时:-
|i-p|≤0 允许 i=p;- 但窗口只有一个位置,根本装不下相邻交换对
(i, i+1);- 所以若按“交换必须完全在窗口里”的语义,
i=p 是误放行。同样地,对一般 r,右端会多出一格:i = p + r。
可复现检查
def allowed_current(p, r, n):
return list(range(max(0, p-r), min(n-1, p+r)+1))def allowed_tight(p, r, n):
return list(range(max(0, p-r), min(n-1, p+r-1)+1))
在 Python 里验证可见:
- current 比 tight 多出的永远是右边界那一格 i = p+r(若边界有效);
- 因而 |i-p|≤r 不是“窗口完全包含交换”的最小必要条件。
统一表述建议
以后若要继续写这个判定,最好显式区分:
-
distance-window:|i-p|≤r-
support-contained-window:p-r ≤ i ≤ p+r-1这样可以避免把“交换起点靠近插入点”与“交换操作完全落在窗口内”混为一谈。