求使数组元素与X按位与和最大的最小X(含K个1比特)
问题分析与解法
你的方法错误原因
你之前的思路(取数组按位或的前K个最高位)忽略了核心逻辑:二进制位的高低不等于它对总和的实际贡献大小。
按位或只能标记数组中是否存在元素在该位为1,但每个位对总和的贡献是「该位为1的元素个数 × 2^位位置」。比如某个高位可能只有少数元素在该位为1,总贡献反而不如一个低位(该位有大量元素为1)。举个实际反例:
- 数组
[8,8,4,4,4,4,4],K=1 - 按位或结果是
12(二进制1100),你的方法会选最高位8,总和是8+8+0+0+0+0+0=16 - 但实际上选低位
4的总和是0+0+4+4+4+4+4=20,显然更大,这时候你的方法就会出错。
简单说,你只看了位的位置高低,没看该位能带来的实际收益,这是核心错误。
更优解法:动态规划贪心组合
我们需要同时满足「总和最大」和「X最小」两个条件,用动态规划可以高效解决,步骤如下:
1. 计算每个位的贡献值
遍历0到30位(覆盖常规整数范围),对每个位i:
- 统计数组中该位为1的元素数量
cnt - 计算该位的总贡献
score = cnt * (1 << i) - 存储每个位的
(score, 位位置i)
2. 排序位
按score从高到低排序;如果两个位的score相同,按位位置i从小到大排序(这样后续选择时,相同贡献下优先选低位,能让X更小)。
3. 动态规划选最优组合
定义dp[k]为选k个位时的两个状态:
- 第一个值:当前最大的总和
- 第二个值:达到该总和的最小X
状态转移
- 初始化
dp[0] = (0, 0),其他dp[k]初始化为(-无穷大, 无穷大) - 遍历每个排序后的位
(score, i):- 从
k = 当前已选最大数量倒序遍历到1:- 如果
dp[k-1].总和 + score > dp[k].总和:更新dp[k]为(dp[k-1].总和 + score, dp[k-1].X | (1 << i)) - 如果
dp[k-1].总和 + score == dp[k].总和:如果新的X(dp[k-1].X | (1 << i))比当前dp[k].X小,就更新X为更小的那个
- 如果
- 从
最终结果
dp[K].X就是满足所有条件的答案。
示例验证
拿你给的例子Arr=[8,4,2],K=2:
- 计算各位置贡献:
- 位3(8):score=1×8=8
- 位2(4):score=1×4=4
- 位1(2):score=1×2=2
- 排序后顺序是
(8,3), (4,2), (2,1) - 动态规划过程:
dp[0]=(0,0)- 处理
(8,3):dp[1]=(8,8) - 处理
(4,2):dp[2]=(12, 12) - 处理
(2,1):无法更新dp[2](总和10<12)
最终dp[2].X=12,符合预期。
内容的提问来源于stack exchange,提问作者Ramesh Suresh
相关产品推荐
相关产品推荐

