首页 > 其他分享 >1879. 两个数组最小的异或值之和

1879. 两个数组最小的异或值之和

时间:2022-10-28 21:46:34浏览次数:72  
标签:mask 枚举 异或 数组 nums1 nums2 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]

复杂度

时间:\(O(n \cdot 2^n)\)
空间:\(O(2^n)\)

总结

题目思路:(1)贪心?乍一看是不是有贪心的做法,但是在其它不等的时候没有啥好思路;(2)怎么遍历两个?题目给了俩数组,不知道怎么用mask表示俩,因为可以任意动,所以值用mask表示一个就行了;(3)怎么用mask表示nums2的选择顺序?不需要顺序,只需要用mask表示nums2的选择情况,只枚举最后一位进行转移就行
代码细节:(1)某位是不是1的判断:判断某一位是不是有1的时候,注意不要写成mask & (1<<i) == 1,因为可能等于(1,2,4,8等等);(2)云端优先级,^运算比加法要低,需要注意括号。

标签:mask,枚举,异或,数组,nums1,nums2,1879
From: https://www.cnblogs.com/zk-icewall/p/16837599.html

相关文章