1879. 两个数组最小的异或值之和
题目描述
给了两个数组nums1和nums2,长度都是n,问怎么排列可以让数组对应元素的异或值之和最小?
f1-二进制枚举+状态压缩 |
基本分析
1.有没有是啥贪心做法,因为看到相同元素异或可以为0?用二进制枚举可以实现这里,还要考虑其他元素,没有啥思路
2.这里涉及到两个元素的排列,枚举需要枚举哪个数组?因为数组是可以任意变动的,就假设1不动,排列2让2去和1一一计算异或和就行了
3.考虑怎么选nums2的顺序?定义f[mask]表示我们选了nums2的的元素状态为mask,且选了数组nums1的前count(mask)个元素情况下的最小异或值之和。这里我们mask只表示选了哪些,具体顺序不管,最小值由枚举最后一位推出来
4.考虑怎么转移?
- 枚举nums2的mask,记下某个mask有多少个1,记为c
- 枚举mask的每一位1,表示这一位1放到最后去和nums1[c]去取异或;f[mask]的最小值就是其中某个转移。
代码
class Solution: def minimumXORSum(self, nums1: List[int], nums2: List[int]) -> int: n = len(nums1) nmask = 1<<n f = [float('inf')] * nmask f[0]=0 for mask in range(1, nmask): # 求出这个mask对应了多少个1 c = bin(mask).count('1') for i in range(n): # 找到了一个1的位置,这个位置可以和nums1[c-1]去取异或 if mask & (1<<i) != 0: f[mask] = min(f[mask], f[mask-(1<<i)] + (nums1[c-1]^nums2[i])) return f[-1]
复杂度
时间:
空间:
总结
题目思路:(1)贪心?乍一看是不是有贪心的做法,但是在其它不等的时候没有啥好思路;(2)怎么遍历两个?题目给了俩数组,不知道怎么用mask表示俩,因为可以任意动,所以值用mask表示一个就行了;(3)怎么用mask表示nums2的选择顺序?不需要顺序,只需要用mask表示nums2的选择情况,只枚举最后一位进行转移就行
代码细节:(1)某位是不是1的判断:判断某一位是不是有1的时候,注意不要写成mask & (1<<i) == 1,因为可能等于(1,2,4,8等等);(2)云端优先级,^运算比加法要低,需要注意括号。
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现