题目
这题的三元组数字是可以重复的,并且不是要恰好等于或者接近 target,而是小于 target 的都行。
解题
这题是 LeetCode1099 小于 K 的两数之和 的进阶版,相当于在 1099 题的基础上加了一层循环。
解题一:二分查找
先对数组进行 排序。两层循环,第一层枚举 a(i = 0; i < n - 2; ++i
),第二层枚举 b(j = i + 1; j < n - 1; ++j
),再利用 二分查找(排序的数组可以进行二分查找)在 [j + 1, n - 1]
范围内寻找 最后一个 < target - a - b 的元素索引 k。如果找不到,则没有符合要求的 c,如果找到了,符合要求的 c 的个数为 k - j。
用 ans 记录 k 逻辑比较简单,但其实 right 也正好符合要求:找不到 c 时,right = j;有一个或多个符合要求的 c 时,right 指向最后一个 c。
// javascript
var threeSumSmaller = function(nums, target) {
const n = nums.length;
let res = 0;
if (n < 3) return res;
nums.sort((a, b) => a - b);
for (let i = 0; i < n - 2; i++) {
// 枚举 a
for (let j = i + 1; j < n - 1; j++) {
// 枚举 b
const value = target - nums[i] - nums[j];
let left = j + 1, right = n - 1; // 在 [j + 1, n - 1] 里寻找最后一个 < target - a - b 的元素索引
// let ans = -1;
while (left <= right) {
const mid = left + ((right - left) >> 1);
if (nums[mid] >= value) {
right = mid - 1;
} else {
// ans = mid;
left = mid + 1;
}
}
// if (ans !== -1) res += (ans - j);
res += (right -