Given an array of n integers nums and a target, find the number of index triplets i, j, k
with 0 <= i < j < k < n
that satisfy the condition nums[i] + nums[j] + nums[k] < target
.
Example:
Input: nums = [-2,0,1,3]
, and target = 2
Output: 2
Explanation: Because there are two triplets which sums are less than 2:
[-2,0,1]
[-2,0,3]
Follow up: Could you solve it in O(n2) runtime?
這道題是 3Sum 問題的一個變形,讓我們求三數之和小於一個目標值,那么最簡單的方法就是窮舉法,將所有的可能的三個數字的組合都遍歷一遍,比較三數之和跟目標值之間的大小,小於的話則結果自增1,參見代碼如下:
解法一:
// O(n^3) class Solution { public: int threeSumSmaller(vector<int>& nums, int target) { int res = 0; sort(nums.begin(), nums.end()); for (int i = 0; i < int(nums.size() - 2); ++i) { int left = i + 1, right = nums.size() - 1, sum = target - nums[i]; for (int j = left; j <= right; ++j) { for (int k = j + 1; k <= right; ++k) { if (nums[j] + nums[k] < sum) ++res; } } } return res; } };
題目中的 Follow up 讓我們在 O(n^2) 的時間復雜度內實現,那么借鑒之前那兩道題 3Sum Closest 和 3Sum 中的方法,采用雙指針來做,這里面有個 trick 就是當判斷三個數之和小於目標值時,此時結果應該加上 right-left,因為數組排序了以后,如果加上 num[right] 小於目標值的話,那么加上一個更小的數必定也會小於目標值,然后將左指針右移一位,否則將右指針左移一位,參見代碼如下:
解法二:
// O(n^2) class Solution { public: int threeSumSmaller(vector<int>& nums, int target) { if (nums.size() < 3) return 0; int res = 0, n = nums.size(); sort(nums.begin(), nums.end()); for (int i = 0; i < n - 2; ++i) { int left = i + 1, right = n - 1; while (left < right) { if (nums[i] + nums[left] + nums[right] < target) { res += right - left; ++left; } else { --right; } } } return res; } };
Github 同步地址:
https://github.com/grandyang/leetcode/issues/259
類似題目:
Two Sum Less Than K
參考資料: