Iter-4360dd15-0170-fact-tight-windowed-swap-condition

fact lesson 4360dd15 local insertion erratum verification

修改:20260424233433000

迭代 170:|i-p|≤r 不是“窗口完全包含交换”的最紧形式

本轮把前两轮的经验判定再收紧了一步:如果我们把“窗口”理解为**插入点 p 周围半径 r 的位置集合**,并要求一次相邻交换的两个被交换位置 ii+1 都落在该窗口内,那么上一轮写成的

|i-p| ≤ r

并不是最紧、也不是完全对齐语义的条件。

两种语义


- 锚点距离语义:只要求交换起点 i 距离插入点 p 不超过 r
- 这对应:|i-p| ≤ r
- 支持集包含语义:要求被交换的两个位置 ii+1 都在窗口 [p-r, p+r] 内。
- 这对应:p-r ≤ ii+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 里验证可见:
- currenttight 多出的永远是右边界那一格 i = p+r(若边界有效);
- 因而 |i-p|≤r 不是“窗口完全包含交换”的最小必要条件。

统一表述建议


以后若要继续写这个判定,最好显式区分:
- distance-window|i-p|≤r
- support-contained-windowp-r ≤ i ≤ p+r-1

这样可以避免把“交换起点靠近插入点”与“交换操作完全落在窗口内”混为一谈。