【教3妹学编程-算法题】最大异或乘积

还是单身狗

3妹:2哥,你有没有看到新闻“18岁父亲为4岁儿子落户现身亲子鉴定”
2哥 : 啥?18岁就当爹啦?
3妹:确切的说是14岁好吧。
2哥 : 哎,想我30了, 还是个单身狗。
3妹:别急啊, 2嫂肯定在某个地方等着你去娶她呢。又不是结婚越早越好。
2哥:是啊, 这孩子14岁当爹,也太早了。
3妹:2哥,你找女朋友有什么条件没有哇?
2哥 : emmm, 以前希望找一个温柔漂亮的, 现在嘛, 女的、活的。毕竟年龄已经很大了, 已经30了…
3妹:才30而已嘛, 女生很多都喜欢找个比自己大一点的~
2哥 : 哎,你们女生最大能接受比自己大多少岁啊?
3妹:emmm, 这么不好说,要看具体女生,一般大个3-5岁都可以吧。 2哥说到最大, 我今天看到一个最大异或乘积的题目,让我也来考考你吧~

考考你

题目:

给你三个整数 a ,b 和 n ,请你返回 (a XOR x) * (b XOR x) 的 最大值 且 x 需要满足 0 <= x < 2n。

由于答案可能会很大,返回它对 109 + 7 取余 后的结果。

注意,XOR 是按位异或操作。

示例 1:

输入:a = 12, b = 5, n = 4
输出:98
解释:当 x = 2 时,(a XOR x) = 14 且 (b XOR x) = 7 。所以,(a XOR x) * (b XOR x) = 98 。
98 是所有满足 0 <= x < 2n 中 (a XOR x) * (b XOR x) 的最大值。
示例 2:

输入:a = 6, b = 7 , n = 5
输出:930
解释:当 x = 25 时,(a XOR x) = 31 且 (b XOR x) = 30 。所以,(a XOR x) * (b XOR x) = 930 。
930 是所有满足 0 <= x < 2n 中 (a XOR x) * (b XOR x) 的最大值。
示例 3:

输入:a = 1, b = 6, n = 3
输出:12
解释: 当 x = 5 时,(a XOR x) = 4 且 (b XOR x) = 3 。所以,(a XOR x) * (b XOR x) = 12 。
12 是所有满足 0 <= x < 2n 中 (a XOR x) * (b XOR x) 的最大值。

提示:

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

思路:

思考

位运算,
详细见代码:

java代码:

class Solution {
    public int maximumXorProduct(long a, long b, int n) {
        if (a < b) {
            // 保证 a >= b
            long temp = a;
            a = b;
            b = temp;
        }

        long mask = (1L << n) - 1;
        long ax = a & ~mask; // 第 n 位及其左边,无法被 x 影响,先算出来
        long bx = b & ~mask;
        a &= mask; // 低于第 n 位,能被 x 影响
        b &= mask;

        long left = a ^ b; // 可分配:a XOR x 和 b XOR x 一个是 1 另一个是 0
        long one = mask ^ left; // 无需分配:a XOR x 和 b XOR x 均为 1
        ax |= one; // 先加到异或结果中
        bx |= one;

        // 现在要把 left 分配到 ax 和 bx 中
        // 根据基本不等式(均值定理),分配后应当使 ax 和 bx 尽量接近,乘积才能尽量大
        if (left > 0 && ax == bx) {
            // 尽量均匀分配,例如把 1111 分成 1000 和 0111
            long highBit = 1L << (63 - Long.numberOfLeadingZeros(left));
            ax |= highBit;
            left ^= highBit;
        }
        // 如果 a & ~mask 更大,则应当全部分给 bx(注意最上面保证了 a>=b)
        bx |= left;

        final long MOD = 1_000_000_007;
        return (int) (ax % MOD * (bx % MOD) % MOD); // 注意不能直接 long * long,否则溢出
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值