leetcode
leetcode 2501 ~ 2550
最大异或乘积

最大异或乘积

难度:

标签:

题目描述

Given three integers a, b, and n, return the maximum value of (a XOR x) * (b XOR x) where 0 <= x < 2n.

Since the answer may be too large, return it modulo 109 + 7.

Note that XOR is the bitwise XOR operation.

 

Example 1:

Input: a = 12, b = 5, n = 4
Output: 98
Explanation: For x = 2, (a XOR x) = 14 and (b XOR x) = 7. Hence, (a XOR x) * (b XOR x) = 98. 
It can be shown that 98 is the maximum value of (a XOR x) * (b XOR x) for all 0 <= x < 2n.

Example 2:

Input: a = 6, b = 7 , n = 5
Output: 930
Explanation: For x = 25, (a XOR x) = 31 and (b XOR x) = 30. Hence, (a XOR x) * (b XOR x) = 930.
It can be shown that 930 is the maximum value of (a XOR x) * (b XOR x) for all 0 <= x < 2n.

Example 3:

Input: a = 1, b = 6, n = 3
Output: 12
Explanation: For x = 5, (a XOR x) = 4 and (b XOR x) = 3. Hence, (a XOR x) * (b XOR x) = 12.
It can be shown that 12 is the maximum value of (a XOR x) * (b XOR x) for all 0 <= x < 2n.

 

Constraints:

  • 0 <= a, b < 250
  • 0 <= n <= 50

代码结果

运行时间: 24 ms, 内存: 16.8 MB


/*
  思路:
  1. 使用 Java Stream API 实现相同的逻辑。
  2. 利用 IntStream.rangeClosed 生成 x 的范围 0 <= x < 2^n。
  3. 对每个 x 计算 (a XOR x) * (b XOR x),并取模 10^9 + 7。
  4. 返回这些计算结果中的最大值。
*/

import java.util.stream.IntStream;

public class Solution {
    public int maxProduct(int a, int b, int n) {
        int maxX = (1 << n) - 1; // 2^n - 1
        int MOD = 1000000007;
        return IntStream.rangeClosed(0, maxX)
                .mapToLong(x -> ((long)(a ^ x) * (long)(b ^ x)) % MOD)
                .max()
                .orElse(0);
    }
}

解释

方法:

此题解通过利用位运算的特性来优化找到最大乘积的过程。首先,确保a不小于b,以简化后续操作。接着,定义一个mask来限制x的范围(确保x小于2^n)。将a和b分别与mask的补码(~mask)和mask本身进行AND操作,得到高位部分(ax, bx)和低位部分(ay, by)。计算ay和by的异或(XOR)结果left,它代表a和b在mask范围内的差异位。接下来,计算一个值one,它是mask与left的异或结果,用于将ax和bx调整到尽可能大的值以获得较大的乘积。在调整过程中,如果left不为0且ax与bx相等,还会进一步调整ax和bx,以确保它们能取到可能的最大值。最后,计算ax与bx的乘积,并取模10^9+7得到结果。

时间复杂度:

O(1)

空间复杂度:

O(1)

代码细节讲解

🦆
题解中提到首先确保a不小于b以简化操作,这种做法是基于什么理论或原理?
确保a不小于b是为了减少算法中的条件判断,从而简化程序的逻辑。由于乘法操作是交换性的(即a*b与b*a的结果相同),选择较大的数作为a可以减少在后续处理中的分支判断,尤其是在涉及位运算优化时,这种处理可以保持一致性,使得代码更加简洁和高效。
🦆
在题解中使用的mask是如何确保x的值不超过2^n的?具体是如何作用的?
在题解中,mask是通过表达式`(1 << n) - 1`计算得到的。这个表达式得到的结果是一个二进制数,其中从最低位到第n位都是1,其余位都是0。这样的掩码用于通过与操作(AND)限制整数的位数。当`a & mask`或`b & mask`执行时,这个操作保留了整数的最低n位,而将高于n的位都置为0。因此,这保证了不管a或b的实际大小如何,通过mask处理后的结果都不会超过2^n-1,从而确保x的值在指定的位范围内。
🦆
题解中提到将a和b分割为高位和低位部分进行操作,这样分割的目的和好处是什么?
将a和b分割为高位和低位部分的主要目的是为了分别处理,从而在位运算中实现更细致的控制和优化。通过这种分割,可以独立地优化a和b的低位部分(通过异或操作找出差异位),同时保留高位部分的信息。这样的分割使得算法可以在不同的位级别上调整数值,以求得最大的乘积结果。此外,这种方式也便于实现基于位操作的优化策略,如进一步调整和对齐位以增大乘积值。
🦆
为什么在调整ax和bx时,要引入一个变量one来进行操作,这个变量具体是如何计算和作用的?
变量one在算法中的作用是用于调整ax和bx,使其尽可能大,以获得更大的乘积结果。one的计算方法是`mask ^ left`,其中left是ay和by的异或结果,代表了a和b在低位的差异位。通过将mask与left异或,one的结果中的1位代表了在ax和bx中需要设置为1的位,以使这两个数尽可能大。因此,`ax |= one`和`bx |= one`的操作确保了在不改变已有的差异位的情况下,尽可能将ax和bx的其他位也设置为1,从而使得最终的乘积最大化。

相关问题