算法01_较小的三数之和


题目

给定一个长度为 n 的整数数组和一个目标值 target,寻找能够使条件

nums[i] + nums[j] + nums[k] < target 成立的三元组 i, j, k

个数(0 <= i < j < k < n)。

思路:排序 + 二分查找排序 + 对撞指针等三种方法

1.暴力求解

三个for循环

时间复杂度O(n^3),其中 n 是数组的长度。

空间复杂度O(1),未开辟额外存储空间。

int threeSumSmaller(int* nums, int numsSize, int target){
    int cnt = 0;
    for (int i = 0; i < numsSize - 2; ++i) {
        for (int j = i + 1; j < numsSize - 1; ++j) {
            for (int k = j + 1; k < numsSize; ++k) {
                if (nums[i] + nums[j] + nums[k] < target) {
                    cnt++;
                }
            }
        }
    }
    
    return cnt;
}

 2.排序 + 二分查找

时间复杂度O(n^2lgn),其中 n 是数组的长度。

空间复杂度O(1),未开辟额外存储空间。

int threeSumSmaller(vector& nums, int target) {
    int cnt = 0;
    int size = nums.size();
    sort(nums.begin(), nums.end());
    for (int i = 0; i < size - 2; ++i) {
        for (int j = i + 1; j < size - 1; ++j) {
            int sum = target - nums[i] - nums[j];
            int left = j + 1, right = size - 1;
            while (left <= right) {
                int mid = left + (right - left) / 2;
                if (nums[mid] >= sum) {
                    right = mid - 1;
                } else {
                    left = mid + 1;
                }
            }
            cnt += (right - j);
        }
    }
    return cnt;
}

 3.排序 + 对撞指针

时间复杂度O(n^2),其中 n 是数组的长度。

空间复杂度O(1),未开辟额外存储空间。

int threeSumSmaller(vector& nums, int target) {
    int cnt = 0;
    int size = nums.size();
    sort(nums.begin(), nums.end());
    for (int i = 0; i < size - 2; ++i) {
        int sum = target - nums[i];
        int left = i + 1, right = size - 1;
        while (left < right) {
            if (nums[left] + nums[right] < sum) {
                cnt += (right - left);
                left++;
            } else {
                right--;
            }
        }
    }

    return cnt;
}