题目重点:把同值首末区间的重叠闭包转为最细分段,最少操作等于不同值数减区间分量数。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- 替换是全局、可选任意不同目标值,每次成本1;不是只改一个位置或移动元素。
- 元素可hash,空输入0;没有保留特定值或限定可替换方向。
解题路线
- 每值v的first..last范围必须在最终同一值块内,因为全局替换永不把原v拆到多个final value。两个原值区间重叠就不能成为两个不同连续块,必须最终合并。
- 这种约束有传递性:区间重叠图每连通分量的c种值至少要合成一个值。一次替换最多减少一个不同值类,因此至少c-1操作;所有分量相加下界U-C。
- 扫描last positions维护当前right=max(last[value]),到i==right才能封口一个分量,类似Partition Labels。分段内没有值跨界,每段恰是区间重叠闭包。
- 每段选一个已有值作为目标,把段内其他c-1值全局替换成它;这些值不出段,不破坏其他段,得到一连续块并达到下界。无需模拟每次替换全数组。
- 如果允许单点改值、元素交换或指定目标限制,该公式不再自动成立;输入原题这里明确全局替换所以保留合并单调性。
手动走一遍
训练[A,B,A,C,B,D,D]前五项形成A/B/C一个闭包、D独立,U=4,C=2,答案2;可把B与C都换A得到五个A接两个D。A,A,B,C,C无需任何操作。
Python 参考实现
下面的代码按上文假设实现,适合本地运行并追加自己的测试用例。
代码区可横向滚动;使用键盘时,先聚焦代码区再按方向键查看。
def minimum_global_replacements(values):
"""One operation replaces every occurrence of one value by another value."""
last={value:i for i,value in enumerate(values)}
components=0
right=-1
for i,value in enumerate(values):
right=max(right,last[value])
if i==right:components+=1
return len(last)-components
复杂度
O(n)期望时间、O(U)last表;输出具体操作需记录每段不同值并产生U-C个动作,实际逐次修改数组可更慢但并非计算最少次数所需。
易错点与追问
容易失分的边界
- 把全局替换误当单点编辑。
- 只数相邻值变化。
- 两个跨界值不合并闭包。
继续深挖
- 限制目标值集合时怎样改下界与构造?
- 要输出替换序列如何选择每段目标?
- 一个新值是否能降低次数?
