题目重点:分别处理a<b和a≤b,连接左右段的整数可行条件不同。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- 值为无界整数,只能修改至多一个位置;返回连续子段长度,不是子序列。
- strict=True要求严格递增,对应严格版本;False采用非降重建版本。AI重建文本的细则不能当统一合同。
解题路线
- left[i]/right[i]分别为不修改时以i结束/开始的最长合法段。保留不改的最大值。
- 假设改i,可以延伸左段+新值,也可以新值+右段,无界整数总能单边满足。要同时桥接,需要选整数x满足a[i−1]<x<a[i+1],即右−左≥2;非降只需左≤右。
- 枚举每个修改点取max(left+1,right+1,left+right+1若可桥接)。最优修改段要么含改点且只向一侧伸展,要么两侧都伸展,枚举完整。
手动走一遍
[1,2,100,4,5]改100为3得到长5。若邻值2和3严格版无中间整数,不能桥接;非降版可选2或3。空数组0,单元素1;“必须修改”若允许改为同值需再确认。
Python 参考实现
下面的代码按上文假设实现,适合本地运行并追加自己的测试用例。
代码区可横向滚动;使用键盘时,先聚焦代码区再按方向键查看。
def longest_one_change(a, strict=True):
n=len(a)
if not n:return 0
def ordered(x,y):return x<y if strict else x<=y
left=[1]*n;right=[1]*n
for i in range(1,n):
if ordered(a[i-1],a[i]):left[i]=left[i-1]+1
for i in range(n-2,-1,-1):
if ordered(a[i],a[i+1]):right[i]=right[i+1]+1
answer=max(left)
for i in range(n):
l=left[i-1] if i else 0;r=right[i+1] if i+1<n else 0
answer=max(answer,l+1,r+1)
if i and i+1<n and (a[i+1]-a[i-1]>=2 if strict else a[i-1]<=a[i+1]):
answer=max(answer,l+1+r)
return answer
复杂度
O(n)时间、O(n)空间;需要返回修改值/下标时保存最优方案与合同边界。
易错点与追问
容易失分的边界
- 浮点数域只要left<right便可能桥接,不能沿用整数差≥2。
- 非降允许重复,不能把严格版本代码无条件用于AI重建描述。
继续深挖
- 值还有限定上下界时单侧延伸何时失效?
- 允许改两次,怎样定义状态或使用区间可行性?
