This commit is contained in:
2026-07-20 19:57:25 +08:00
parent 4fa78d4c00
commit 124ad9afdf
26 changed files with 2715 additions and 5 deletions
+109
View File
@@ -0,0 +1,109 @@
package misc
import "testing"
// 题目(推测题干)
//
// 给定两个长度为 n 的 0/1 数组 a 和 b。
// 一次操作:选择 [L, R, V],满足 1 ≤ L ≤ R ≤ nV ∈ {0,1}
// 将 a 中下标在 [L,R] 内的所有元素统一修改为 V(区间外不变)。
//
// 问:是否存在恰好一种操作使 a 变为 b?
// - 存在且唯一:输出该操作 [L,R,V](0-indexed 闭区间)
// - 不存在或不唯一:输出 -1
//
// 思路(0-indexed
//
// 记 need = { i : a[i] != b[i] },即必须被改到的位置。
//
// 1. 找 lo = min(need), hi = max(need)。need 为空 → a == b,特判(见下)。
// 2. 区间 [L,R] 必须 ⊇ [lo, hi],否则 need 中落在区间外的位置不会被改。
// 3. 区间内每个位置改完都要等于 b;而一个操作只有一个 V,
// 所以 [lo,hi] 内 b 必须全相同,V = b[lo]。否则无解 (-1)。
// 4. L 的取值范围:L ≤ lo。向左能扩张到 b 中连续等于 V 的位置
// (这些位置改后仍等于 b,不破坏)。
// - L 唯一 ⟺ lo == 0(到左边界)或 b[lo-1] != V(左边紧邻不等于 V,无法扩张)
// 5. R 的取值范围:R ≥ hi。向右能扩张到 b 中连续等于 V 的位置。
// - R 唯一 ⟺ hi == n-1(到右边界)或 b[hi+1] != V
// 6. L、R 都唯一 → 输出 [lo, hi, V];否则 -1。
//
// 特判 a == bneed 为空):
// - 要一次操作让 a 不变:区间内 a 必须全等于 V。
// - 任何单点 [i,i] 配 V=a[i] 都可行。
// - n == 1:唯一解 [0, 0, a[0]]。
// - n >= 2:有多个单点选择 → 不唯一 → -1。
func uniqueRangeAssign(a, b []int) (L, R, V int, ok bool) {
n := len(a)
// 第 1 步:找 lo, hi
lo, hi := -1, -1
for i := 0; i < n; i++ {
if a[i] != b[i] {
if lo == -1 {
lo = i
}
hi = i
}
}
// 特判 a == b
if lo == -1 {
if n == 1 {
return 0, 0, a[0], true
}
return 0, 0, 0, false
}
// 第 3 步:V = b[lo],检查 [lo,hi] 内 b 全等于 V
V = b[lo]
for i := lo; i <= hi; i++ {
if b[i] != V {
return 0, 0, 0, false
}
}
// 第 4 步:L 唯一性
lOK := lo == 0 || b[lo-1] != V
// 第 5 步:R 唯一性
rOK := hi == n-1 || b[hi+1] != V
if !lOK || !rOK {
return 0, 0, 0, false
}
// 第 6 步:唯一解
return lo, hi, V, true
}
func TestUniqueRangeAssign(t *testing.T) {
cases := []struct {
name string
a, b []int
wantL int
wantR int
wantV int
wantOK bool
}{
{"唯一-全改", []int{0, 0}, []int{1, 1}, 0, 1, 1, true},
{"唯一-部分改", []int{0, 0, 0, 0, 0}, []int{1, 1, 1, 0, 0}, 0, 2, 1, true},
{"唯一-右扩", []int{0, 0, 0, 0, 0}, []int{0, 0, 1, 1, 1}, 2, 4, 1, true},
{"无解-内部b不一致", []int{0, 1, 0}, []int{1, 0, 1}, 0, 0, 0, false},
{"不唯一-R可扩", []int{0, 1, 1}, []int{1, 1, 1}, 0, 0, 0, false},
{"不唯一-L可扩", []int{1, 0, 1}, []int{1, 1, 1}, 0, 0, 0, false},
{"不唯一-a=b,n>=2", []int{1, 1, 1}, []int{1, 1, 1}, 0, 0, 0, false},
{"唯一-a=b,n=1", []int{0}, []int{0}, 0, 0, 0, true},
{"唯一-单点改", []int{0}, []int{1}, 0, 0, 1, true},
{"唯一-覆盖整个数组", []int{1, 1, 0, 1}, []int{0, 0, 0, 0}, 0, 3, 0, true},
{"无解-need不连续且b不一致", []int{0, 0, 0, 0}, []int{1, 0, 0, 1}, 0, 0, 0, false},
}
for _, c := range cases {
L, R, V, ok := uniqueRangeAssign(c.a, c.b)
pass := ok == c.wantOK &&
(!ok || (L == c.wantL && R == c.wantR && V == c.wantV))
if !pass {
t.Errorf("%s: a=%v b=%v -> [%d,%d,%d] ok=%v, want [%d,%d,%d] ok=%v",
c.name, c.a, c.b, L, R, V, ok, c.wantL, c.wantR, c.wantV, c.wantOK)
}
}
}