题目描述
大致思路, 经过昨天那道题后发现解决这种问题使用双指针更加简单, 于是思路为for循环(i)单层遍历数组, 将数组从大到小排序, 定义一头一尾指针 j与k, 然后拿到 val = nums[i] + nums[j] + nums[k]. 如果val < target, 则j++, val > target 则 k--, val === target 则直接retrun val. 需要注意的点是 i、j、k 三个值不能相等。该部分代码如下:
const tmp: number[] = [];
for (let i = 1; i < nums.length - 1; ++i) {
let j = 0;
let k = nums.length - 1;
while (j < k) {
const val = nums[i] + nums[j] + nums[k];
if (val === target) return target;
if (val < target) {
if (++j === i) ++j;
}
if ((val > target)) {
if (--k === i) --k;
}
tmp.push(val);
}
}
拿到数组和的集合后需要做的事情就是取到 集合每个元素与target差值的绝对值的集合中最小的那个值的 index, 最后tmp[index]即为最接近的数据
该部分代码:
const min = tmp.map((item) => Math.abs(target - item)).sort((a, b) => a - b)[0];
const index = tmp.map((item) => Math.abs(target - item)).findIndex((item) => item === min);
最后主题函数:
export function threeSumClosest(nums: number[], target: number): number {
if (nums.length < 3) return 0;
nums.sort((a, b) => a - b);
const tmp: number[] = [];
for (let i = 1; i < nums.length - 1; ++i) {
let j = 0;
let k = nums.length - 1;
while (j < k) {
const val = nums[i] + nums[j] + nums[k];
if (val === target) return target;
if (val < target) {
if (++j === i) ++j;
}
if ((val > target)) {
if (--k === i) --k;
}
tmp.push(val);
}
}
const min = tmp.map((item) => Math.abs(target - item)).sort((a, b) => a - b)[0];
const index = tmp.map((item) => Math.abs(target - item)).findIndex((item) => item === min);
return tmp[index];
}
//测试用例:
test('threeSumClosest', () => {
expect(threeSumClosest([-1, 2, 1, -4], 1)).toBe(2);
expect(threeSumClosest([1, 4, 3, -4, 2], 1)).toBe(1);
expect(threeSumClosest([0, 0, 0, 1], 1)).toBe(1);
expect(threeSumClosest([0, 0, 0], 1)).toBe(0);
});
最后总结: 神奇的双指针...