“Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。”
一、题目描述
给你一个整数数组 nums ,它包含 2 * n 个整数。
你需要将 nums 划分成 n 个数对,满足:
- 每个元素 只属于一个 数对。
- 同一数对中的元素 相等 。
如果可以将 nums 划分成 n 个数对,请你返回 true ,否则返回 false 。
示例 1:
输入: nums = [3,2,3,2,2,2]
输出: true
解释:
nums 中总共有 6 个元素,所以它们应该被划分成 6 / 2 = 3 个数对。
nums 可以划分成 (2, 2) ,(3, 3) 和 (2, 2) ,满足所有要求。
示例 2:
输入: nums = [1,2,3,4]
输出: false
解释:
无法将 nums 划分成 4 / 2 = 2 个数对且满足所有要求。
提示:
nums.length == 2 * n1 <= n <= 5001 <= nums[i] <= 500
二、思路分析
题目要求划分的 nums.length / 2 个数对中每个元素都要相同且不重复,如果可以做到则 return true ,否则 return false 。
题意很简单,有多个方法可以完成,下面说说两个比较好的解法。
解法一,哈希表,思路如下:
- 建一个空间大小为
nums.length + 1的数组arr,并赋值为0,用来标识nums中每个元素有多少个。 - 遍历
arr数组,如果当前元素不是2的倍数,说明该元素无法配对成 两个元素都相同 的数对,则return false。 - 如果遍历到最后依然能配对成功,则说明可以满足题意,
return true。
解法二,排序,思路如下:
- 从小到大排序
nums数组。 - 从
0开始遍历nums数组,如果当前元素等于其后一个元素,则可以匹配成数对,这时遍历到当前元素的后两个元素,继续判断是否相等;如果不相等的话,后面也不可能会有与当前元素相等的值了(因为数组已经是升序的了),直接return false。
三、AC 代码
解法一:哈希表
var divideArray = function(nums) {
const arr = new Array(501).fill(0);
for (let x of nums) {
arr[x]++;
}
for (let x of arr) {
if (x % 2 !== 0) {
return false;
}
}
return true;
};
解法二:排序
var divideArray = function(nums) {
nums.sort((a, b) => a - b);
for (let i = 0; i < nums.length; i += 2) {
if (nums[i] !== nums[i + 1]) {
return false;
}
}
return true;
};
四、总结
这道题本身不难,需要注意的是第一种解法,我用 js 写的时候没有给 arr 数组定大小,导致建了一个空数组,不能给元素赋值,一直为 NaN ,看到题目的提示 1 <= nums[i] <= 500 才意识到给 arr 数组定大小即可。
稍微拓展一下,js 创建数组的几种方式:
var a = Array();
var b = new Array();
var c = [];
这几种方式都能成功创建数组,在实际使用中:
- 从性能上来讲,new Array() 在初始化大数组的时候,性能更加优异
- 从语言特性上讲,虽然使用
new,会增加多一层的对象包裹,而使得内存冗余。但使用new后更加符合了 js 对象化继承的概念。自我感觉上,使用new应该是更加好的方式。