题目来源:🔒LeetCode259:较小的三数之和
问题抽象: 给定整数数组 nums 和目标整数 target,要求统计所有满足 和小于 target 的三元组 (i, j, k) 的数量,需满足以下核心需求:
-
三元组定义:
- 索引约束:
i < j < k(三元组由三个不同位置的元素组成); - 数值约束:
nums[i] + nums[j] + nums[k] < target(严格小于); - 重复处理:不同索引的相同元素视为独立元素(如
[1,1,2]中(0,1,2)和(1,0,2)视为同一三元组?不,索引唯一性确保三元组唯一)。
- 索引约束:
-
输入约束:
- 数组长度
n ∈ [0, 5000]; - 元素值
∈ [-10^3, 10^3],目标值target ∈ [-10^3, 10^3]; - 需处理 重复元素(如
[1,1,1])。
- 数组长度
-
输出要求:
- 返回满足条件的三元组 总数(非具体列表);
- 示例:
nums=[-2,0,1,3],target=2→ 输出2(三元组(-2,0,1)和(-2,0,3))。
-
计算约束:
- 时间复杂度 O(n²)(三重循环
O(n³)超时,需优化); - 空间复杂度 O(1)(除排序栈外仅用常数空间)。
- 时间复杂度 O(n²)(三重循环
-
关键策略:
- 排序预处理:将
nums升序排序(O(n log n)); - 双指针优化:
- 固定索引
i(0 ≤ i < n-2); - 双指针
j=i+1,k=n-1; - 当
nums[i]+nums[j]+nums[k] < target时:- 所有
k' ∈ [j+1, k]均满足条件 → 计数+ (k-j); j右移;
- 所有
- 否则
k左移。
- 固定索引
- 排序预处理:将
输入:整数数组 nums(如 [-2,0,1,3]),目标整数 target(如 2)
输出:整数(满足条件的三元组数量,如 2)。
解题思路
-
排序预处理
- 将数组排序,使双指针策略生效。排序后,数组元素按升序排列,便于通过指针移动控制三数之和的大小。
-
固定外层元素+双指针
- 外层循环:遍历每个元素
nums[i]作为三元组的第一个元素(范围[0, n-2])。 - 内层双指针:
- 初始化
left = i + 1(三元组第二个元素),right = n - 1(三元组第三个元素)。 - 计算当前和
sum = nums[i] + nums[left] + nums[right]。 - 关键优化:
- 若
sum < target:
所有以(i, left)为前两个元素、right在(left, right]范围内的三元组均满足条件(共right - left个)。累加后右移left。 - 若
sum >= target:
说明当前和过大,需左移right减小和值。
- 若
- 初始化
- 外层循环:遍历每个元素
-
时间复杂度: 排序:O(n log n)。 双指针遍历:O(n²)(外层 O(n),内层双指针合计 O(n))。 总时间复杂度:O(n²),满足进阶要求。 空间复杂度:O(1)(未使用额外空间)。
代码实现(Java版)🔥点击下载源码
class Solution {
public int threeSumSmaller(int[] nums, int target) {
int n = nums.length;
if (n < 3) return 0; // 数组长度不足3时无解
Arrays.sort(nums); // 排序确保双指针有效
int count = 0;
for (int i = 0; i < n - 2; i++) {
int left = i + 1, right = n - 1;
// 双指针遍历内层范围
while (left < right) {
int sum = nums[i] + nums[left] + nums[right];
if (sum < target) {
// 所有以 (i,left) 开头、right∈(left, right] 的三元组均满足条件
count += right - left;
left++; // 移动左指针以尝试更大值
} else {
right--; // 和过大,右指针左移
}
}
}
return count;
}
}
代码说明
-
排序的必要性
- 排序后,数组元素单调递增,使得双指针可以根据当前和与
target的大小关系确定移动方向,确保不漏解。
- 排序后,数组元素单调递增,使得双指针可以根据当前和与
-
双指针的优化逻辑
- 当
sum < target时,由于数组有序,固定i和left时,所有right在(left, right]内的三元组均满足条件。因此直接累加right - left后右移left,避免重复计算。 - 若
sum >= target,右移right可减少和值,逐步逼近有效解。
- 当
-
边界处理
- 数组长度小于 3 时直接返回 0。
- 内层循环严格满足
left < right,防止指针越界。

877

被折叠的 条评论
为什么被折叠?



