【中等】力扣算法题解析LeetCode259:较小的三数之和

关注文末推广名片,即可免费获得本题测试源码

题目来源:🔒LeetCode259:较小的三数之和

问题抽象: 给定整数数组 nums 和目标整数 target,要求统计所有满足 和小于 target 的三元组 (i, j, k) 的数量,需满足以下核心需求:

  1. 三元组定义

    • 索引约束i < j < k(三元组由三个不同位置的元素组成);
    • 数值约束nums[i] + nums[j] + nums[k] < target(严格小于);
    • 重复处理:不同索引的相同元素视为独立元素(如 [1,1,2](0,1,2)(1,0,2) 视为同一三元组?不,索引唯一性确保三元组唯一)。
  2. 输入约束

    • 数组长度 n ∈ [0, 5000]
    • 元素值 ∈ [-10^3, 10^3],目标值 target ∈ [-10^3, 10^3]
    • 需处理 重复元素(如 [1,1,1])。
  3. 输出要求

    • 返回满足条件的三元组 总数(非具体列表);
    • 示例:
      • nums=[-2,0,1,3], target=2 → 输出 2(三元组 (-2,0,1)(-2,0,3))。
  4. 计算约束

    • 时间复杂度 O(n²)(三重循环 O(n³) 超时,需优化);
    • 空间复杂度 O(1)(除排序栈外仅用常数空间)。
  5. 关键策略

    • 排序预处理:将 nums 升序排序(O(n log n));
    • 双指针优化
      1. 固定索引 i0 ≤ i < n-2);
      2. 双指针 j=i+1, k=n-1
      3. nums[i]+nums[j]+nums[k] < target 时:
        • 所有 k' ∈ [j+1, k] 均满足条件 → 计数 + (k-j)
        • j 右移;
      4. 否则 k 左移。

输入:整数数组 nums(如 [-2,0,1,3]),目标整数 target(如 2
输出:整数(满足条件的三元组数量,如 2)。


解题思路

  1. 排序预处理

    • 将数组排序,使双指针策略生效。排序后,数组元素按升序排列,便于通过指针移动控制三数之和的大小。
  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 减小和值。
  3. 时间复杂度: 排序: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;
    }
}

代码说明

  1. 排序的必要性

    • 排序后,数组元素单调递增,使得双指针可以根据当前和与 target 的大小关系确定移动方向,确保不漏解。
  2. 双指针的优化逻辑

    • sum < target 时,由于数组有序,固定 ileft 时,所有 right(left, right] 内的三元组均满足条件。因此直接累加 right - left 后右移 left,避免重复计算。
    • sum >= target,右移 right 可减少和值,逐步逼近有效解。
  3. 边界处理

    • 数组长度小于 3 时直接返回 0。
    • 内层循环严格满足 left < right,防止指针越界。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

达文汐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值