首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >2026-07-06:通过交换使数组相等的最小花费。用go语言,给你两个长度均为 n 的整数数组 nums1 和 nums2。 你可以执行以下操作任意次: 1.

2026-07-06:通过交换使数组相等的最小花费。用go语言,给你两个长度均为 n 的整数数组 nums1 和 nums2。 你可以执行以下操作任意次: 1.

作者头像
福大大架构师每日一题
发布2026-07-06 18:12:40
发布2026-07-06 18:12:40
30
举报

2026-07-06:通过交换使数组相等的最小花费。用go语言,给你两个长度均为 n 的整数数组 nums1 和 nums2。

你可以执行以下操作任意次:

1.同数组内交换(免费)

在同一个数组中任选两个位置 i 和 j,把该位置上的元素互换;nums1 内换、或 nums2 内换都可以。此类操作不花费任何代价。

2.跨数组对应位置交换(费用为 1)

任选一个下标 i,将 nums1[i] 与 nums2[i] 这两个位置的元素互换。每执行一次花费 1。

目标:让最终的 nums1 和 nums2 完全相同。

求完成该目标所需的最小总费用;如果无法做到,返回 -1。

2 <= n == nums1.length == nums2.length <= 80000。

1 <= nums1[i], nums2[i] <= 80000。

输入: nums1 = [10,10], nums2 = [20,20]。

输出: 1。

解释:

交换 nums1[0] = 10 和 nums2[0] = 20。

nums1 变为 [20, 10]。

nums2 变为 [10, 20]。

此操作花费 1。

交换 nums2[0] = 10 和 nums2[1] = 20。

nums2 变为 [20, 10]。

此操作是免费的。

nums1 和 nums2 现在相同。花费为 1。

题目来自力扣3868。

一、题目规则梳理

两种操作规则

  1. 1. 同数组内部交换,免费 nums1内部任意互换元素、nums2内部任意互换元素,不产生任何花费,意味着单个数组内元素的顺序无意义,只看元素多重集合。 比如 nums1=[10,20] 和 nums1=[20,10] 完全等价,不用花钱调整顺序。
  2. 2. 同下标跨数组交换,单次花费1 选下标i,交换 nums1[i] 和 nums2[i],一次操作成本固定为1;只能成对交换对应位置,不能跨下标互换两个数组元素。

最终目标

调整完成后,nums1 的全部元素多重集合 = nums2 的全部元素多重集合。

无解判定条件

把两个数组所有元素合并统计频次后,任意数字出现总次数为奇数 → 无法均分,直接返回 -1。

二、示例输入场景拆解:nums1=[10,10],nums2=[20,20]

全部元素合并:10、10、20、20 总频次:10出现2次,20出现2次,全为偶数,有解。

可行最优方案分步拆解

  1. 1. 执行1次下标0跨数组交换(花费+1) nums1[0]与nums2[0]互换: nums1 = [20,10],nums2 = [10,20]
  2. 2. nums2内部免费交换下标0和1(无花费) nums2变为 [20,10]
  3. 3. 此时 nums1=[20,10]、nums2=[20,10],数组完全一致 总花费仅1,为最优解。

三、原代码核心逻辑分步详细解释

整体思路:利用哈希表统计两个数组元素的差值,通过差值计算最少交换次数。

步骤1:构建差值哈希表 diff,统计每个数字在两数组的数量差

哈希表 key = 数字x,value = 差值d

  1. 1. 遍历 nums1 所有元素:每遇到x,diff[x] += 1 含义:该数字在nums1中比nums2多1个。
  2. 2. 遍历 nums2 所有元素:每遇到x,diff[x] -= 1 含义:该数字在nums2中抵消一个nums1的计数。

以示例代入计算:

  • • 遍历nums1 [10,10]:diff[10] = 2,diff[20]=0
  • • 遍历nums2 [20,20]:diff[10]=2,diff[20]=-2 最终 diff = {10:2, 20:-2}

步骤2:遍历哈希表所有差值,先判断是否无解

逐个取出每个数字对应的差值d:

  1. 1. 判定无解:若 d 是奇数,直接返回 -1 原理:d = nums1中x数量 − nums2中x数量。 两数组最终要完全相等,意味着对任意x,nums1最终x数量 = nums2最终x数量; 所有x的总个数是固定总和,差值必须是偶数才能通过交换均分,奇数差值无法平衡,直接无解。
  2. 2. 累加正数差值到总临时和ans:只加 d>0 的数值 d>0 代表:当前nums1里该数字,比nums2多出d个; d<0 代表:nums2里该数字比nums1多出|d|个,二者是成对互补关系,只统计一侧正数即可避免重复计算。

示例代入: diff[10]=2>0 → ans +=2;diff[20]=-2 不参与累加,此时ans=2。

步骤3:最终花费 = ans / 2,返回结果

数学原理

ans是所有“nums1多出元素”的总数,每一次跨数组交换操作,能同时消除nums1一个多余元素、消除nums2一个多余元素: 每1次交换,能抵消2个多余计数(nums1少1个,nums2少1个)。 所以总交换次数 = 总多余数量 ÷ 2。

示例中ans=2,2/2=1,和题目输出完全匹配。

四、逻辑正确性补充说明

  1. 1. 为什么不用关心下标、不用模拟交换? 因为数组内部交换免费,我们可以自由重排两个数组内元素的顺序,不需要受原始下标束缚;只需要统计两个数组之间元素总量的差值,就能算出最少交换次数。
  2. 2. 为什么只累加正数差值? 对于任意数字x,差值d和-d必然成对出现:所有数字的差值总和一定是0(nums1长度=n,nums2长度=n,总元素数量相等),正数总和 = 负数绝对值总和,只算一侧不会丢失数据。
  3. 3. 最小花费保证: 该统计方式只计算平衡数量所需最少交换次数,不存在更优方案——每一次交换最多消除2个不平衡计数,除以2得到的是理论下界,必然是最小花费。

五、时间复杂度 & 额外空间复杂度分析

1. 时间复杂度 O(n)

设数组长度为n:

  1. 1. 遍历nums1填充哈希表:O(n)
  2. 2. 遍历nums2更新哈希表:O(n)
  3. 3. 遍历哈希表所有键统计差值:哈希表键的总数最多2n(极端所有数字互不相同),整体为O(n) 三段线性操作相加,整体时间复杂度:O(n)

2. 额外空间复杂度 O(n)

哈希表diff存储所有出现过的数字; 最坏情况nums1、nums2全部数字互不重复,哈希表需要存储2n个键值对; 输入数组不计入额外空间,仅统计哈希表占用内存,额外空间复杂度:O(n)

Go完整代码如下:

.

代码语言:javascript
复制
package main

import (
    "fmt"
)

func minCost(nums1, nums2 []int) (ans int) {
    diff := map[int]int{}
    for _, x := range nums1 {
        diff[x]++
    }
    for _, x := range nums2 {
        diff[x]--
    }

    for _, d := range diff {
        if d%2 != 0 {
            return-1
        }
        if d > 0 {
            ans += d
        }
    }
    return ans / 2
}

func main() {
    nums1 := []int{10, 10}
    nums2 := []int{20, 20}
    result := minCost(nums1, nums2)
    fmt.Println(result)
}
在这里插入图片描述
在这里插入图片描述

Python完整代码如下:

.

代码语言:javascript
复制
# -*-coding:utf-8-*-

def minCost(nums1, nums2):
    diff = {}
    # 统计 nums1 的出现次数
    for x in nums1:
        diff[x] = diff.get(x, 0) + 1
    # 减去 nums2 的出现次数
    for x in nums2:
        diff[x] = diff.get(x, 0) - 1

    ans = 0
    for d in diff.values():
        # 如果某个数值的频次差为奇数,则无法匹配
        if d % 2 != 0:
            return-1
        # 只累加正差值,最终结果除以 2
        if d > 0:
            ans += d
    return ans // 2


if __name__ == "__main__":
    nums1 = [10, 10]
    nums2 = [20, 20]
    result = minCost(nums1, nums2)
    print(result)
在这里插入图片描述
在这里插入图片描述

C++完整代码如下:

.

代码语言:javascript
复制
#include <iostream>
#include <vector>
#include <unordered_map>

int minCost(const std::vector<int>& nums1, const std::vector<int>& nums2) {
    std::unordered_map<int, int> diff;

    for (int x : nums1) {
        diff[x]++;
    }
    for (int x : nums2) {
        diff[x]--;
    }

    int ans = 0;
    for (const auto& p : diff) {
        int d = p.second;
        if (d % 2 != 0) {
            return-1;
        }
        if (d > 0) {
            ans += d;
        }
    }
    return ans / 2;
}

int main() {
    std::vector<int> nums1 = {10, 10};
    std::vector<int> nums2 = {20, 20};
    int result = minCost(nums1, nums2);
    std::cout << result << std::endl;
    return0;
}
在这里插入图片描述
在这里插入图片描述

·


我们相信人工智能为普通人提供了一种“增强工具”,并致力于分享全方位的AI知识。在这里,您可以找到最新的AI科普文章、工具评测、提升效率的秘籍以及行业洞察。 欢迎关注“福大大架构师每日一题”,发消息可获得面试资料,让AI助力您的未来发展。

·

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2026-07-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 福大大架构师每日一题 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、题目规则梳理
    • 两种操作规则
    • 最终目标
    • 无解判定条件
  • 二、示例输入场景拆解:nums1=[10,10],nums2=[20,20]
    • 可行最优方案分步拆解
  • 三、原代码核心逻辑分步详细解释
    • 步骤1:构建差值哈希表 diff,统计每个数字在两数组的数量差
    • 步骤2:遍历哈希表所有差值,先判断是否无解
    • 步骤3:最终花费 = ans / 2,返回结果
      • 数学原理
  • 四、逻辑正确性补充说明
  • 五、时间复杂度 & 额外空间复杂度分析
    • 1. 时间复杂度 O(n)
    • 2. 额外空间复杂度 O(n)
  • Go完整代码如下:
  • Python完整代码如下:
  • C++完整代码如下:
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档