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

[排序和二分] 绝对差值和

给你两个正整数数组 nums1 和 nums2 ,数组的长度都是 n 。

数组 nums1 和 nums2 的 绝对差值和 定义为所有 |nums1[i] - nums2[i]|0 <= i < n)的 总和下标从 0 开始)。

你可以选用 nums1 中的 任意一个 元素来替换 nums1 中的 至多 一个元素,以 最小化 绝对差值和。

在替换数组 nums1 中最多一个元素 之后 ,返回最小绝对差值和。因为答案可能很大,所以需要对 109 + 7 取余 后返回。

|x| 定义为:

  • 如果 x >= 0 ,值为 x ,或者
  • 如果 x <= 0 ,值为 -x

示例 1:

输入:nums1 = [1,7,5], nums2 = [2,3,5]
输出:3
解释:有两种可能的最优方案:
- 将第二个元素替换为第一个元素:[1,7,5] => [1,1,5] ,或者
- 将第二个元素替换为第三个元素:[1,7,5] => [1,5,5]
两种方案的绝对差值和都是 |1-2| + (|1-3| 或者 |5-3|) + |5-5| = 3

示例 2:

输入:nums1 = [2,4,6,8,10], nums2 = [2,4,6,8,10]
输出:0
解释:nums1 和 nums2 相等,所以不用替换元素。绝对差值和为 0

示例 3

输入:nums1 = [1,10,4,4,2,7], nums2 = [9,3,5,1,7,4]
输出:20
解释:将第一个元素替换为第二个元素:[1,10,4,4,2,7] => [10,10,4,4,2,7]
绝对差值和为 |10-9| + |10-3| + |4-5| + |4-1| + |2-7| + |7-4| = 20

提示:

  • n == nums1.length
  • n == nums2.length
  • 1 <= n <= 105
  • 1 <= nums1[i], nums2[i] <= 105

解题分析

这题的话需要我们耐心地去分析,首先,我们很容易想到枚举的方法,总共有n^2种情况,我们可以全部遍历然后找到绝对差值和最小的那种情况,最后输出答案即可,不过这种方法显然很容易超时。那有没有更好的方法呢?比如说排序或者二分法?当然可以。我们不妨取出一个局部去观察,首先,对于任意一个位置的i,abs(nums1[i]-nums2[i])就是这个位置对于答案的贡献,如果我们用j位置的数去置换掉i位置(0<=i,j<n,其中n为nums1数组的长度),那么这个位置的贡献就变成了abs(nums1[j]-nums2[i])。两次的差值为maxn = abs(nums1[i]-nums2[i]) - abs(nums1[j]-nums2[i])。那么最终的答案就会变成sum - maxn。我们想让sum最小,只需让maxn最大即可。我们回到表达式中,可以比较清楚地发现,一旦i确定了,我们只需要去寻找一个j,就可以确定这个值,j应该怎么取呢?其实也比较容易发现,我们只需要让nums1[j]接近nums2[i]即可,也就是说我们二分查找一下nums1数组中和nums2[i]接近的两个数(可能更小,也可能更大),然后比较哪个更小即可。这里推荐使用lower_bound,可以比较快地返回一个迭代器,迭代器指向的是大于等于nums2[i]的一个数的位置,由于vector的内存是连续分布的,所以我们可以作减法得到一个下标的位置。

代码实现

class Solution {
public:static constexpr int mod = 1'000'000'007;int minAbsoluteSumDiff(vector<int>& nums1, vector<int>& nums2) {vector<int> rec(nums1);sort(rec.begin(),rec.end());int sum = 0, maxn = 0;int n = nums1.size();for(int i = 0 ; i < n ; i++){int diff = abs(nums1[i] - nums2[i]);sum = (sum + diff) % mod;int j = lower_bound(rec.begin(),rec.end(),nums2[i]) - rec.begin();if(j < n){maxn = max(maxn, diff - (rec[j] - nums2[i]));}if(j > 0){maxn = max(maxn, diff - (nums2[i] - rec[j-1]));}}return (sum - maxn + mod) % mod;}
};

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 联华证券--开盘如何捕捉涨停股?解析哪些股票容易涨停
  • 监控平台之上报(未完成)
  • OpenCV绘图函数(1)绘制带箭头的直线函数arrowedLine()的使用
  • 【电脑小白】告别蓝屏恐慌:一步步教你排查和解决蓝屏问题,从此告别蓝屏烦恼!
  • .NET中分布式服务
  • 版本管理工具 Git 的下载安装及使用
  • 关于几道计算机网络题的解答
  • 采购管理流程:自动化如何使效率提升75% ?
  • uniapp h5可以用indexdb嘛
  • GitHub每日最火火火项目(8.31)
  • 智能导诊系统中,运用的 6大AI 技术详解
  • Having trouble using OpenAI API
  • list类底层逻辑实现
  • 设备管理与文件系统
  • 冻死你都觉得简单
  • [ 一起学React系列 -- 8 ] React中的文件上传
  • [译] React v16.8: 含有Hooks的版本
  • 【跃迁之路】【519天】程序员高效学习方法论探索系列(实验阶段276-2018.07.09)...
  • AHK 中 = 和 == 等比较运算符的用法
  • bootstrap创建登录注册页面
  • flask接收请求并推入栈
  • iOS高仿微信项目、阴影圆角渐变色效果、卡片动画、波浪动画、路由框架等源码...
  • oschina
  • Python利用正则抓取网页内容保存到本地
  • vue:响应原理
  • vuex 学习笔记 01
  • vue数据传递--我有特殊的实现技巧
  • 从tcpdump抓包看TCP/IP协议
  • 当SetTimeout遇到了字符串
  • 精益 React 学习指南 (Lean React)- 1.5 React 与 DOM
  • 浏览器缓存机制分析
  • 移动互联网+智能运营体系搭建=你家有金矿啊!
  • 容器镜像
  • 专访Pony.ai 楼天城:自动驾驶已经走过了“从0到1”,“规模”是行业的分水岭| 自动驾驶这十年 ...
  • ​ArcGIS Pro 如何批量删除字段
  • ​LeetCode解法汇总2670. 找出不同元素数目差数组
  • ​LeetCode解法汇总2808. 使循环数组所有元素相等的最少秒数
  • ​中南建设2022年半年报“韧”字当头,经营性现金流持续为正​
  • # Pytorch 中可以直接调用的Loss Functions总结:
  • ###51单片机学习(2)-----如何通过C语言运用延时函数设计LED流水灯
  • $(document).ready(function(){}), $().ready(function(){})和$(function(){})三者区别
  • ( 10 )MySQL中的外键
  • (bean配置类的注解开发)学习Spring的第十三天
  • (pojstep1.1.1)poj 1298(直叙式模拟)
  • (二) 初入MySQL 【数据库管理】
  • (二)PySpark3:SparkSQL编程
  • (翻译)terry crowley: 写给程序员
  • (附源码)计算机毕业设计SSM基于java的云顶博客系统
  • (官网安装) 基于CentOS 7安装MangoDB和MangoDB Shell
  • (计算机网络)物理层
  • (亲测)设​置​m​y​e​c​l​i​p​s​e​打​开​默​认​工​作​空​间...
  • (三)终结任务
  • (原創) 如何讓IE7按第二次Ctrl + Tab時,回到原來的索引標籤? (Web) (IE) (OS) (Windows)...
  • (转)菜鸟学数据库(三)——存储过程
  • (转)重识new