class Solution:
def twoSumLessThanK(self, nums, k):
nums.sort()
left, right = 0, len(nums) - 1
max_sum = -1
while left < right:
curr_sum = nums[left] + nums[right]
if curr_sum < k:
max_sum = max(max_sum, curr_sum)
left += 1
else:
right -= 1
return max_sum
class Solution {
public:
int twoSumLessThanK(vector<int>& nums, int k) {
sort(nums.begin(), nums.end());
int left = 0, right = nums.size() - 1;
int max_sum = -1;
while (left < right) {
int curr_sum = nums[left] + nums[right];
if (curr_sum < k) {
max_sum = max(max_sum, curr_sum);
left++;
} else {
right--;
}
}
return max_sum;
}
};
import java.util.Arrays;
class Solution {
public int twoSumLessThanK(int[] nums, int k) {
Arrays.sort(nums);
int left = 0, right = nums.length - 1;
int maxSum = -1;
while (left < right) {
int currSum = nums[left] + nums[right];
if (currSum < k) {
maxSum = Math.max(maxSum, currSum);
left++;
} else {
right--;
}
}
return maxSum;
}
}
var twoSumLessThanK = function(nums, k) {
nums.sort((a, b) => a - b);
let left = 0, right = nums.length - 1;
let maxSum = -1;
while (left < right) {
let currSum = nums[left] + nums[right];
if (currSum < k) {
maxSum = Math.max(maxSum, currSum);
left++;
} else {
right--;
}
}
return maxSum;
};
Given an array of integers nums and an integer k, your task is to find the maximum sum of any two distinct elements in nums such that the sum is less than k. If no such pair exists, return -1.
nums can be used at most once in the sum (no element can pair with itself).k, or -1 if none exists.
When first approaching this problem, a simple way to think about it is to try every possible pair of numbers and check if their sum is less than k. For each valid pair, we keep track of the largest sum found so far. This brute-force approach works, but it becomes slow as the array grows larger.
To optimize, we notice that sorting the array allows us to use a two-pointer technique. By sorting, we can efficiently find pairs with sums close to but less than k without checking every possible pair. This reduces unnecessary checks and speeds up the solution.
The key insight is: after sorting, if the sum of the smallest and largest is too big, we can decrease the largest; if it's small enough, we can try increasing the smallest to get closer to k.
k using two pointers.left at the start (smallest number) and right at the end (largest number).left < right:
curr_sum = nums[left] + nums[right].curr_sum < k: update max_sum if this sum is larger, and move left right to try a bigger sum.curr_sum ≥ k: move right left to try a smaller sum.-1.
This approach is efficient because sorting is O(n log n) and the two-pointer scan is O(n).
Let's use nums = [34, 23, 1, 24, 75, 33, 54] and k = 60.
nums: [1, 23, 24, 33, 34, 54, 75]left = 0 (1), right = 6 (75).1 + 75 = 76 (too big), move right to 5.1 + 54 = 55 (< 60), update max_sum = 55, move left to 1.23 + 54 = 77 (too big), move right to 4.23 + 34 = 57 (< 60), update max_sum = 57, move left to 2.24 + 34 = 58 (< 60), update max_sum = 58, move left to 3.33 + 34 = 67 (too big), move right to 3.left is not less than right).
The largest sum less than 60 is 58.
O(n^2) (check every pair)O(1) (no extra space needed)O(n log n) (due to sorting; two-pointer scan is O(n))O(1) (if sorting in place)The optimized approach is much faster for larger arrays because it avoids checking every possible pair.
The Two Sum Less Than K problem is a great example of how sorting and the two-pointer technique can turn a slow brute-force solution into an efficient one. By sorting the array, we can quickly zoom in on the best possible pair using two pointers, only checking pairs that might yield a better result. This approach is both simple and elegant, making the solution efficient even for large inputs.