数组元素配对求最大XOR和:为何最大生成树可行?
给定一个数组,重复执行以下操作直到数组仅剩一个元素:
- 随机选取两个元素
a和b,将a XOR b的值加入结果answer - 丢弃其中一个元素,将另一个放回数组
要求计算answer的最大值。
示例
输入数组:arr = [3,2,1]
输出:5
操作流程:
- 选取2和1,计算
2^1=3加入结果,丢弃2,数组变为[3,1] - 选取3和1,计算
3^1=2加入结果,丢弃3,数组仅剩[1]
总和3+2=5即为最大值。
困惑点
用递归回溯可以解决,但时间复杂度是O(N!),效率极低。了解到可以用**最大生成树(MaxST)**来解决,但无法理解其合理性:
模拟场景:用Prim算法构建最大生成树,假设首条边选(A,B),下一条选连接A或B的最大权重边(A,C);接着选连接A、B、C的最大权重边(B,D)。此时(A,C)和(B,D)都被纳入MaxST,但按照问题规则,选(A,B)后必须丢弃A或B——如果丢B,后续根本没法选(B,D);如果丢A,后续没法选(A,C),不可能同时选这两条边。
这里的核心疑问是:最大生成树中的每条边对应一次a^b的操作(即把该值加入answer),但按照问题的操作规则,似乎无法同时选中MaxST里的所有边,那为什么最大生成树的总权重就是答案的最大值?
为什么最大生成树可行?
关键在于操作顺序的可调整性——我们可以把每个元素看作图中的节点,节点u和v之间的边权重设为u^v。问题的操作过程本质是构建一棵包含n-1条边的树(n为数组元素个数),而最大生成树的总权重就是能达到的最大总和,原因如下:
你之前的误区是默认了固定的操作顺序(先选(A,B)),但实际上操作顺序完全可以调整,只要按照“先处理叶子节点”的逻辑,就能把MaxST的所有边对应的XOR值都计入总和。比如刚才的A、B、C、D场景:
假设MaxST的边是(A,B)、(A,C)、(B,D),总权重是(A^B)+(A^C)+(B^D),我们可以这样操作:
- 先选C和A,计算
A^C加入结果,丢弃C,数组保留A、B、D - 选D和B,计算
B^D加入结果,丢弃D,数组保留A、B - 选A和B,计算
A^B加入结果,丢弃其中一个,数组只剩一个元素
这样三条边的XOR值都被计入了总和,和MaxST的总权重完全一致。
更深层的逻辑是:这个问题的最大值等价于所有节点构成的最大生成树的总权重。因为每次合并操作相当于保留两个节点的XOR贡献,而最大生成树恰好选择了能让总贡献最大的n-1条边,且这些边可以通过合理调整操作顺序全部被利用。
内容的提问来源于stack exchange,提问作者thenonacmguy

