持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第4天,点击查看活动详情
面试题 16.21. 交换和
给定两个整数数组,请交换一对数值(每个数组中取一个数值),使得两个数组所有元素的和相等。
返回一个数组,第一个元素是第一个数组中要交换的元素,第二个元素是第二个数组中要交换的元素。若有多个答案,返回任意一个均可。若无满足条件的数值,返回空数组。
「示例1:」
输入: array1 = [4, 1, 2, 1, 1, 2], array2 = [3, 6, 3, 3]
输出: [1, 3]
「示例2:」
输入: array1 = [1, 2, 3], array2 = [4, 5, 6]
输出: []
「提示:」
1 <= array1.length, array2.length <= 100000
解题思路
// 第一种
一般套路,先求两个数组总和sum1+sum2,得到两数组各自的目标和target,再逐个遍历数组array2,对任意一个数字num,如果把它换到array1中且array1中存在target - (sum2-num),则num和target - (sum2-num)就是结果
// 第二种
先判断两个数组的和是不是相等,相等的话不用做任何操作
在判断和相加是不是偶数,如果不是,不能凑成两个和相等的数组
剩下就是可能的情况了
先求的两个数组和的差值,目标值就是差值除以2的值,只要我们能从和大的数组中取出一个数,减去和小的数组中取出一个数,差值为目标值,这两个数就是结果
先将两个数组排序
里用双指针,分别从和大的数组、和小的数组中分别取得一个数,取两个数的差值
如果差值小于目标值,减数要增加,就移动和大的数组的指针
如果差值大于目标值,被减数就要增加,就移动和小的数组的指针
直至结束
代码实现
// 第一种
var findSwapValues = function(array1, array2) {
let sum1 = 0, sum2 = 0
for(const num of array1) sum1 += num
for(const num of array2) sum2 += num
const target = (sum1 + sum2) / 2
if(target !== Math.floor(target)) return []
const set = new Set(array1)
for(let num of array2) {
if(set.has(target - (sum2 - num))) return [target - (sum2 - num), num]
}
return []
};
// 第二种
/**
* @param {number[]} array1
* @param {number[]} array2
* @return {number[]}
*/
var findSwapValues = function(array1, array2) {
const total1 = array1.reduce((a, b) => a + b)
const total2 = array2.reduce((a, b) => a + b)
const total = total1 + total2
if (total1 === total2 || total % 2) return []
array1.sort((a, b) => a - b)
array2.sort((a, b) => a - b)
let minArr = array1, maxArr = array2, arr1 = true, differ = (total2 - total1) >>> 1
if (total2 < total1) {
minArr = array2
maxArr = array1
arr1 = false
differ = (total1 - total2) >>> 1
}
const l1 = minArr.length, l2 = maxArr.length
let l = 0, r = 0
while(l < l1 && r < l2) {
const dif = maxArr[r] - minArr[l]
if (dif < differ) {
r++
} else if (dif > differ) {
l++
} else {
return arr1 ? [minArr[l], maxArr[r]] : [maxArr[r], minArr[l]]
}
}
return []
};
如果你对这道题目还有疑问的话,可以在评论区进行留言;