本文正在参与掘金团队号上线活动,点击 查看大厂春招职位
一、题目描述:
二、思路分析:
今天给大家分享的是力扣第235场周赛的第三题,当初比赛的时候AC了,没想到最后被rejude了。今天再重新做一遍看看吧。
错误的解法
比赛的时候我的想法是找出一个绝对值差值最大的位置,然后从nums1找到一个数字,替换这个位置上的nums1的数字。但是这其实是不对的,如下面这个case就无法通过。 [1,28,21] [9,21,20]
OK,我们再来重新看一下题目,题目有提到【最小化】,数据量10^5。所以我们可以往O(NlogN)的复杂度上考虑。力扣上有好多道题目是有类似字眼的,都可以使用二分解法。
二分查找
首先我们考虑一下暴力解法,我们会枚举nums1的每个位置,然后尝试用nums1其他位置的数字替换当前位置的数字,重新计算一下绝对值和,最后求一个最小值,但是时间复杂度是O(N^2),不能满足题目的要求。所以我们可以在寻找每个位置的替换数字时,可以考虑找到一个最接近nums1[i]的数字,可以使用二分查找快速找到。
- 时间复杂度:O(NlogN),这里 N 是数组的长度。
- 空间复杂度:O(N),使用到的临时变量的个数是常数。
三、AC 代码:
class Solution {
/**
* @param Integer[] $nums1
* @param Integer[] $nums2
* @return Integer
*/
function minAbsoluteSumDiff($nums1, $nums2) {
$n = count($nums1);
$diff = 0;
for ($i = 0; $i < $n; $i++) {
$temp = (int)(abs($nums1[$i] - $nums2[$i]));
$diff += $temp;
}
if ($diff == 0) {
return 0;
}
$min = PHP_INT_MAX;
$tempArr = $nums1;
sort($tempArr);
echo $diff;
for ($i = 0; $i < $n; $i++) {
$temp = (int)(abs($nums1[$i] - $nums2[$i]));
if ($temp == 0) {
continue;
}
$target = $nums2[$i];
$tttt = $this->find($tempArr, 0, $n - 1, $target);
echo $temp.':'.$target.':'.$tttt.PHP_EOL;
$min = min($min, $diff - $temp + $tttt);
}
return $min % (1000000000 + 7);
}
protected function find($nums, $left, $right, $target) {
$min = PHP_INT_MAX;
while ($left < $right) {
$mid = $left + (int)(($right - $left + 1) / 2);
if ($nums[$mid] - $target > 0) {
$right = $mid - 1;
$min = min($min, $nums[$mid] - $target);
} elseif ($nums[$mid] - $target < 0) {
$left = $mid;
$min = min($min, abs($nums[$mid] - $target));
} else {
return 0;
}
}
return min($min, abs($nums[$left] - $target));
}
}
四、总结: