LeetCode 259. 较小的三数之和

259. 较小的三数之和

给定一个长度为 n 的整数数组和一个目标值 target ,寻找能够使条件 nums[i] + nums[j] + nums[k] < target 成立的三元组  i, j, k 个数(0 <= i < j < k < n)。

示例 1:

输入: nums = [-2,0,1,3], target = 2
输出: 2 
解释: 因为一共有两个三元组满足累加和小于 2:
     [-2,0,1]
     [-2,0,3]

示例 2:

输入: nums = [], target = 0
输出: 0 

示例 3:

输入: nums = [0], target = 0
输出: 0 

提示:

  • n == nums.length
  • 0 <= n <= 3500
  • -100 <= nums[i] <= 100
  • -100 <= target <= 100

解法: 双指针 + 两数之和

当我们需要枚举数组中的两个元素时,如果我们发现随着第一个元素的递增,第二个元素是递减的,那么就可以使用双指针的方法,将枚举的时间复杂度从 O(N^2) 减少至 O(N)。为什么是 O(N) 呢?这是因为在枚举的过程每一步中,「左指针」会向右移动一个位置(也就是题目中的 j),而「右指针」会向左移动若干个位置,这个与数组的元素有关,但我们知道它一共会移动的位置数为 O(N),均摊下来,每次也向左移动一个位置,因此时间复杂度为 O(N)。

注意到我们的代码中还有第一重循环,时间复杂度为 O(N),因此枚举的总时间复杂度为 O(N^2)。由于排序的时间复杂度为 O(Nlog⁡N),在渐进意义下小于前者,因此算法的总时间复杂度为 O(N^2)。

类似题型:

LeetCode 15. 三数之和-优快云博客

LeetCode 16. 最接近的三数之和-优快云博客

LeetCode 1099. 小于 K 的两数之和-优快云博客

class Solution {
    public int threeSumSmaller(int[] nums, int target) {
        int ans = 0;
        int n = nums.length;
        if (n < 3) {
            return 0;
        }
        Arrays.sort(nums);
        for (int i = 0; i < n - 2; i++) {
            // nums[j] + nums[k] < target - nums[i]
            // 数组是排好序的,固定i,则枚举j的过程中,符合要求的k一定是逐渐减小的
            int k = n - 1;
            for (int j = i + 1; j < n - 1; j++) {
                // nums[k] < target - nums[i] - nums[j]
                while (k > j && nums[i] + nums[j] + nums[k] >= target) {
                    k--;
                }
                if (k == j) {
                    break;
                }
                // 由于数组是排好序的,此时固定i,j,k是满足要求的最大值
                // 此时 (j,k]之间的数目是满足要求的k的数目
                ans += k - j;
            }
        }
        return ans;
    }
}

复杂度分析 

  • 时间复杂度:O(N ^ 2),N 是数组nums 的长度。数组排序的时间复杂度是O(N logN)。
  • 空间复杂度:O(1)。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值