Files
leetcode/misc/unique-range-assign/leetcode_test.go
T
2026-07-20 19:57:25 +08:00

109 lines
3.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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)
}
}
}