当前位置: 首页 > news >正文

【月度刷题计划同款】常规状压 DP 启发式搜索

题目描述

这是 LeetCode 上的 「1879. 两个数组最小的异或值之和」 ,难度为 「困难」

Tag : 「状压 DP」、「动态规划」、「启发式搜索」

给你两个整数数组 nums1nums2,它们长度都为 n

两个数组的 异或值之和 为 (nums1[0] XOR nums2[0]) + (nums1[1] XOR nums2[1]) + ... + (nums1[n - 1] XOR nums2[n - 1]) (下标从 0 开始)。

比方说,[1,2,3][3,2,1] 的 异或值之和 等于 (1 XOR 3) + (2 XOR 2) + (3 XOR 1) = 2 + 0 + 2 = 4

请你将 nums2 中的元素重新排列,使得异或值之和最小 。

请你返回重新排列之后的 异或值之和 。

示例 1:

输入:nums1 = [1,2], nums2 = [2,3]

输出:2

解释:将 nums2 重新排列得到 [3,2] 。
异或值之和为 (1 XOR 3) + (2 XOR 2) = 2 + 0 = 2 。

示例 2:

输入:nums1 = [1,0,3], nums2 = [5,3,4]

输出:8

解释:将 nums2 重新排列得到 [5,4,3] 。
异或值之和为 (1 XOR 5) + (0 XOR 4) + (3 XOR 3) = 4 + 4 + 0 = 8 。

提示:

状压 DP

这是一道「状压 DP」模板题。

为了方便,我们令下标从 开始。

「定义 为考虑前 个元素,且对 nums2 的使用情况为 时的最小异或值」。其中 是一个长度为 的二进制数:若 中的第 位为 ,说明 nums2[k] 已被使用;若 中的第 位为 ,说明 nums2[k] 未被使用。

起始时,只有 ,其余均为无穷大 INF 含义为在不考虑任何数,对 nums2 没有任何占用情况时,最小异或值为 。最终 即为答案。

不失一般性考虑 该如何转移,可以以 nums1[i] 是与哪个 nums2[j] 进行配对作为切入点:

  • 由于总共考虑了前 个成员,因此 的数量必然为 ,否则 就不是一个合法状态,跳过转移

  • 枚举 nums1[i] 是与哪一个 nums2[j] 进行配对的,且枚举的 需满足在 中的第 位值为 ,若满足则有

其中 prev 为将 中的第 位进行置零后的二进制数,即 prev = s ^ (1 << j),符号 ⊕ 代表异或操作。

Java 代码:

class Solution {
    public int minimumXORSum(int[] nums1, int[] nums2) {
        int n = nums1.length, mask = 1 << n, INF = 0x3f3f3f3f;
        int[][] f = new int[n + 10][mask];
        for (int i = 0; i <= n; i++) Arrays.fill(f[i], INF);
        f[0][0] = 0;
        for (int i = 1; i <= n; i++) {
            for (int s = 0; s < mask; s++) {
                if (getCnt(s, n) != i) continue;
                for (int j = 1; j <= n; j++) {
                    if (((s >> (j - 1)) & 1) == 0continue;
                    f[i][s] = Math.min(f[i][s], f[i - 1][s ^ (1 << (j - 1))] + (nums1[i - 1] ^ nums2[j - 1]));
                }
            }
        }
        return f[n][mask - 1];
    }
    int getCnt(int s, int n) {
        int ans = 0;
        for (int i = 0; i < n; i++) ans += (s >> i) & 1;
        return ans;
    }
}

C++ 代码:

class Solution {
public:
    int minimumXORSum(vector<int>& nums1, vector<int>& nums2) {
        int n = nums1.size(), mask = 1 << n, INF = 0x3f3f3f3f;
        vector<vector<int>> f(n + 10vector<int>(mask, INF));
        f[0][0] = 0;
        auto getCnt = [&](int s, int n) {
            int ans = 0;
            for (int i = 0; i < n; i++) ans += (s >> i) & 1;
            return ans;
        };
        for (int i = 1; i <= n; i++) {
            for (int s = 0; s < mask; s++) {
                if (getCnt(s, n) != i) continue;
                for (int j = 1; j <= n; j++) {
                    if (((s >> (j - 1)) & 1) == 0continue;
                    f[i][s] = min(f[i][s], f[i - 1][s ^ (1 << (j - 1))] + (nums1[i - 1] ^ nums2[j - 1]));
                }
            }
        }
        return f[n][mask - 1];
    }
};

Python 代码:

class Solution:
    def minimumXORSum(self, nums1: List[int], nums2: List[int]) -> int:
        n, mask, INF = len(nums1), 1 << len(nums1), 0x3f3f3f3f
        f = [[INF] * mask for _ in range(n + 10)]
        f[0][0] = 0
        for i in range(1, n + 1):
            for s in range(mask):
                if sum([1 for i in range(n) if (s >> i) & 1]) != i:
                    continue
                for j in range(1, n + 1):
                    if ((s >> (j - 1)) & 1) == 0:
                        continue
                    f[i][s] = min(f[i][s], f[i - 1][s ^ (1 << (j - 1))] + (nums1[i - 1] ^ nums2[j - 1]))
        return f[n][mask - 1]

TypeScript 代码:

function minimumXORSum(nums1: number[], nums2: number[]): number {
    const n = nums1.length, mask = 1 << n, INF = 0x3f3f3f3f;
    const f: number[][] = new Array(n + 10).fill([]).map(() => new Array(mask).fill(INF));
    f[0][0] = 0;
    const getCnt = (s: number, n: number): number => {
        let ans = 0;
        for (let i = 0; i < n; i++) ans += (s >> i) & 1;
        return ans;
    };
    for (let i = 1; i <= n; i++) {
        for (let s = 0; s < mask; s++) {
            if (getCnt(s, n) !== i) continue;
            for (let j = 1; j <= n; j++) {
                if (((s >> (j - 1)) & 1) === 0continue;
                f[i][s] = Math.min(f[i][s], f[i - 1][s ^ (1 << (j - 1))] + (nums1[i - 1] ^ nums2[j - 1]));
            }
        }
    }
    return f[n][mask - 1];
};
  • 时间复杂度:
  • 空间复杂度:

模拟退火

事实上,这道题还能使用「模拟退火」进行求解。

由于我们可以无限次对 nums2 进行打乱互换,先来思考如何衡量一个 nums2 排列的“好坏”。

一个简单的方式:固定计算 (nums1[0] XOR nums2[0]) + (nums1[1] XOR nums2[1]) + ... + (nums1[n - 1] XOR nums2[n - 1]) 作为衡量当前 nums2 的得分,得分越小,当前的 nums2 排列越好。

迭代开始前先对 nums2 进行一次随机打乱,随后每个回合随机选择 nums2 的两个成员进行互换,并比较互换前后的得分情况,若互换后变好,那么保留该互换操作;若变差,则以一定概率进行重置(重新换回来)。

重复迭代多次,使用一个全局变量 ans 保存下最小异或值之和。

即「模拟退火」的单次迭代基本流程:

  1. 随机选择两个下标,计算「交换下标元素前对应序列的得分」&「交换下标元素后对应序列的得分」
  2. 如果温度下降(交换后的序列更优),进入下一次迭代
  3. 如果温度上升(交换前的序列更优),以「一定的概率」恢复现场(再交换回来)

对于一个能够运用模拟退火求解的问题,最核心的是如何实现 calc 方法(即如何定义一个具体方案的得分),其余均为模板内容。

Java 代码(2023/08/23 可过):

class Solution {
    int N = 400;
    double hi = 1e5, lo = 1e-5, fa = 0.90;
    Random random = new Random(20230823);
    void swap(int[] n, int a, int b) {
        int c = n[a];
        n[a] = n[b];
        n[b] = c;
    }
    int calc() {
        int res = 0;
        for (int i = 0; i < n; i++) res += n1[i] ^ n2[i];
        ans = Math.min(ans, res);
        return res;
    }
    void shuffle(int[] nums) {
        for (int i = n; i > 0; i--) swap(nums, random.nextInt(i), i - 1);
    }
    void sa() {
        shuffle(n2);
        for (double t = hi; t > lo; t *= fa) {
            int a = random.nextInt(n), b = random.nextInt(n);
            int prev = calc();
            swap(n2, a, b);
            int cur = calc(); 
            int diff = cur - prev; 
            if (Math.log(diff / t) >= random.nextDouble()) swap(n2, a, b);
        }
    }
    int[] n1, n2;
    int n;
    int ans = Integer.MAX_VALUE;
    public int minimumXORSum(int[] nums1, int[] nums2) {
        n1 = nums1; n2 = nums2;
        n = n1.length;
        while (N-- > 0) sa();
        return ans;
    }
}
  • 时间复杂度:启发式搜索不讨论时空复杂度
  • 空间复杂度:启发式搜索不讨论时空复杂度

最后

这是我们「刷穿 LeetCode」系列文章的第 No.1879 篇,系列开始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完。

在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。

为了方便各位同学能够电脑上进行调试和提交代码,我建立了相关的仓库:https://github.com/SharingSource/LogicStack-LeetCode 。

在仓库地址里,你可以看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和其他优选题解。

更多更全更热门的「笔试/面试」相关资料可访问排版精美的 合集新基地 🎉🎉

相关文章:

【月度刷题计划同款】常规状压 DP 启发式搜索

题目描述 这是 LeetCode 上的 「1879. 两个数组最小的异或值之和」 &#xff0c;难度为 「困难」。 Tag : 「状压 DP」、「动态规划」、「启发式搜索」 给你两个整数数组 nums1 和 nums2&#xff0c;它们长度都为 n。 两个数组的 异或值之和 为 (nums1[0] XOR nums2[0]) (nums…...

C#: Json序列化和反序列化,集合为什么多出来一些元素?

如下面的例子&#xff0c;很容易看出问题&#xff1a; 如果类本身的无参构造函数&#xff0c; 就添加了一些元素&#xff0c;序列化&#xff0c;再反序列化&#xff0c;会导致元素增加。 如果要避免&#xff0c;必须添加&#xff1a; new JsonSerializerSettings() { Object…...

Docker教程-centos快速安装和配置Docker

# step 1: 安装必要的一些系统工具 sudo yum install -y yum-utils device-mapper-persistent-data lvm2# Step 2: 添加软件源信息 sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo# Step 3: 更新并安装 Docker-CE sudo …...

three.js(四):react + three.js

绘制多个立方体 1.搭建reactts 项目 npx create-react-app basics-demo --template typescriptreactts 的用法可参考此链接&#xff1a; https://react-typescript-cheatsheet.netlify.app/docs/basic/setup 2.安装three依赖 npm install three types/three --save3.安装路…...

IDEA全局统一设置Maven

原来每次打开新建的项目都需要经过 File-> Settings 重新配置maven&#xff0c;这样很不爽 然而经过 File-> New Projects Setup -> Settings for New Projects 后&#xff0c;再如上图配置后就全局设置好了...

CSS中的margin与padding

目录 一、margin 1.概念及作用 2.基本语法 3.margin的用法 二、padding 1.介绍 2.基本语法及要求 3. 用法 4.内边距和元素宽度 讲这些之前&#xff0c;先看一张图&#xff0c;便于理解 一、margin 1.概念及作用 CSS margin 属性用于在任何定义的边框之外&#xff0c;…...

匿名内部类、Lambda、方法引用 的总结

在今天的项目中看到这样一行代码 Integer syncCount consumer.consumerInfo( Collections.singletonList(KafkaTopicConst.Event_BMS_SYSLOG_ROLE),consumer::handle); 直接傻眼&#xff0c;无法理解consumer::handle这种用法&#xff0c;因此总结如下 consumer::handle这种写…...

本地docker registry 搭建

#!/bin/bash DOCKER_REGISTRY_ROOT/data0/docker/registry DOMAINexample.host.com #生成证书&#xff1a;https://goharbor.io/docs/2.6.0/install-config/configure-https/ mkdir $DOCKER_REGISTRY_ROOT/certs cd $DOCKER_REGISTRY_ROOT/certs openssl genrsa -out ca.key 40…...

阿里云将关停代销业务

我是卢松松&#xff0c;点点上面的头像&#xff0c;欢迎关注我哦&#xff01; 阿里云自从逐渐分拆独立之后&#xff0c;做了很多调整。最近它又做了一个大动作&#xff1a;据DoNews消息&#xff0c;阿里云将会在今年9月30日之前&#xff0c;全面关停代销业务。 这件事实际上…...

【ES6】JavaScript的Proxy:理解并实现高级代理功能

在JavaScript中&#xff0c;Proxy是一种能够拦截对对象的读取、设置等操作的机制。它们提供了一种方式&#xff0c;可以在执行基本操作之前或之后&#xff0c;对这些操作进行自定义处理。这种功能在许多高级编程场景中非常有用&#xff0c;比如实现数据验证、日志记录、权限控制…...

[Pandas] 求百分比并添加百分(%)号

导入数据 import pandas as pddf pd.DataFrame(data{orders: [2130,5102,3256,1297,1918,786],repeat_orders: [73,158,89,30,49,18]}) df df[repetition_rate] df[repeat_orders] / df[orders] df df[repetition_rate] df[repetition_rate].apply(lambda x: format(x, .2…...

《算法竞赛·快冲300题》每日一题:“凑二十四”

《算法竞赛快冲300题》将于2024年出版&#xff0c;是《算法竞赛》的辅助练习册。 所有题目放在自建的OJ New Online Judge。 用C/C、Java、Python三种语言给出代码&#xff0c;以中低档题为主&#xff0c;适合入门、进阶。 文章目录 题目描述题解C代码Java代码Python代码 “ 凑…...

git reset --hard HEAD

git reset --hard HEAD 是用于将你的工作目录重置回最后一次提交状态的命令。- git reset 是 git 的一个命令&#xff0c;用于重置你当前的 HEAD 到指定的状态。 --hard 标志告诉 git 要完全重置工作目录和暂存区&#xff0c;去匹配最后一次提交。在这个过程中&#xff0c;所有…...

机器人编程怎么入门?

机器人已经在我们中间存在了二三十年。如今&#xff0c;机器人在我们的文化中比以往任何时候都更加根深蒂固。大多数机器人机器用于各种装配线&#xff0c;或在世界各地的矿山或工业设施中执行密集的物理操作。 还有一些家用机器人&#xff0c;工程师正在对机器人进行编程&…...

广州华锐互动:VR垃圾分类虚拟科普系统让学习过程更加丰富有趣

在我们的日常生活中&#xff0c;垃圾分类已成为一项重要的公民责任。然而&#xff0c;由于缺乏对垃圾分类的深入理解和相关知识&#xff0c;许多人在实践中往往感到困惑和挫败。为了解决这个问题&#xff0c;一种创新的解决方案应运而生&#xff1a;垃圾分类VR虚拟仿真教学系统…...

手机盖板IR油墨透光率检测仪T03

手机盖板作为手机最外层玻璃面板&#xff0c;其加工一般有落料、倒边、抛光、镀膜、丝印等多道加工工序组成&#xff0c;其中任何一个工序出现差错&#xff0c;都有可能导致手机盖板产生缺陷&#xff0c;例如漏油、透光、IR孔不良、视窗划伤、油墨区划伤、內污、边花等&#xf…...

ChatGPT⼊门到精通(6):ChatGPT 提问设计

前⾔ 学会提问就是为了让AI给出⾼质量的答案。 你所学到的技能⼀切为了⽣成⾼质量的答案。 本教程适合&#xff1a;普通ChatGPT的⽤户、专业prompt⼯程师 你将收获&#xff1a;prompt 技巧的全⾯指导 、prompt⼯程师必备技能、prompt技术⼯程⾼质量答 案完全指南 提⽰词 Prom…...

如何使用 Tailwind CSS 设计高级自定义动画

使用Tailwind CSS掌握动画技术&#xff0c;为用户带来难忘的体验 开篇 动画已经成为网页设计的重要组成部分&#xff0c;使开发人员能够创建引人入胜和互动的用户体验。 Tailwind CSS&#xff0c;一款流行的实用型CSS框架&#xff0c;提供了一套强大的工具&#xff0c;可以轻松…...

【C语言】循环语句详解

✨个人主页&#xff1a; Anmia.&#x1f389;所属专栏&#xff1a; C Language &#x1f383;操作环境&#xff1a; Visual Studio 2019 版本 目录 1.什么是循环结构&#xff1f; 2.while循环 while流程图 while语句中的break和continue break continue 3.for循环 for流…...

SpringBoot项目配置文件数据库用户名密码加密

1、需求 在使用SpringBoot开发过程中&#xff0c;会将一些敏感信息配置到SpringBoot项目的配置文件中(不考虑使用配置中心的情况 )&#xff0c;例如数据库的用户名和密码、Redis的密码等。为了保证敏感信息的安全&#xff0c;我们需要将此类数据进行加密配置。 2、操作步骤 …...

线程同步:确保多线程程序的安全与高效!

全文目录&#xff1a; 开篇语前序前言第一部分&#xff1a;线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分&#xff1a;synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分&#xff…...

【第二十一章 SDIO接口(SDIO)】

第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...

Nginx server_name 配置说明

Nginx 是一个高性能的反向代理和负载均衡服务器&#xff0c;其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机&#xff08;Virtual Host&#xff09;。 1. 简介 Nginx 使用 server_name 指令来确定…...

ElasticSearch搜索引擎之倒排索引及其底层算法

文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...

Ascend NPU上适配Step-Audio模型

1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统&#xff0c;支持多语言对话&#xff08;如 中文&#xff0c;英文&#xff0c;日语&#xff09;&#xff0c;语音情感&#xff08;如 开心&#xff0c;悲伤&#xff09;&#x…...

涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战

“&#x1f916;手搓TuyaAI语音指令 &#x1f60d;秒变表情包大师&#xff0c;让萌系Otto机器人&#x1f525;玩出智能新花样&#xff01;开整&#xff01;” &#x1f916; Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制&#xff08;TuyaAI…...

大数据学习(132)-HIve数据分析

​​​​&#x1f34b;&#x1f34b;大数据学习&#x1f34b;&#x1f34b; &#x1f525;系列专栏&#xff1a; &#x1f451;哲学语录: 用力所能及&#xff0c;改变世界。 &#x1f496;如果觉得博主的文章还不错的话&#xff0c;请点赞&#x1f44d;收藏⭐️留言&#x1f4…...

智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制

在数字化浪潮席卷全球的今天&#xff0c;数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具&#xff0c;在大规模数据获取中发挥着关键作用。然而&#xff0c;传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时&#xff0c;常出现数据质…...

sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!

简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求&#xff0c;并检查收到的响应。它以以下模式之一…...

虚拟电厂发展三大趋势:市场化、技术主导、车网互联

市场化&#xff1a;从政策驱动到多元盈利 政策全面赋能 2025年4月&#xff0c;国家发改委、能源局发布《关于加快推进虚拟电厂发展的指导意见》&#xff0c;首次明确虚拟电厂为“独立市场主体”&#xff0c;提出硬性目标&#xff1a;2027年全国调节能力≥2000万千瓦&#xff0…...