算法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<int>& 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<int>& 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; }