Given an integer array arr[], find the sum of any two elements whose sum is closest to zero.
Note: In case if we have two ways to form sum closest to zero, return the maximum sum among them.
Examples:
Input: arr[] = [-8, 5, 2, -6]
Output: -1
Explanation: The min absolute sum pair is (5, -6)Input: arr[] = [0, -8, -6, 3]
Output: 3
Explanation: We have a tie between (0, 3) and (-6, 3). We pick the max sum in this case which is 0+3Input: arr[] = [-7, 4, 1, -2]
Output: -1
Explanation: The min absolute sum pair is (1, -2).
Table of Content
[Naive Approach] Check Every Possible Pair - O(n^2) Time and O(1) Space
The idea is to use the naive method that checks the sum of every possible pair of elements in the array and keeps track of the pair with the minimum absolute sum.
#include <bits/stdc++.h>
using namespace std;
int closestToZero(vector<int>& arr) {
// Initialize result with sum of first two elements
int res = arr[0] + arr[1];
// Check all pairs
for (int i = 0; i < arr.size() - 1; i++) {
for (int j = i + 1; j < arr.size(); j++) {
int sum = arr[i] + arr[j];
if (abs(sum) < abs(res)) {
res = sum;
}
else if (abs(sum) == abs(res)) {
res = max(res, sum);
}
}
}
return res;
}
int main() {
vector<int> arr = {0, -8, -6, 3};
cout << closestToZero(arr);
return 0;
}
import java.util.*;
class GFG {
static int closestToZero(int[] arr) {
// Initialize the result with the sum
// of the first two elements
int res = arr[0] + arr[1];
// Consider every pair, find its sum and
// update result if we get a smaller value
for (int i = 0; i < arr.length - 1; i++) {
for (int j = i + 1; j < arr.length; j++) {
int sum = arr[i] + arr[j];
if (Math.abs(sum) < Math.abs(res)) {
res = sum;
}
else if (Math.abs(sum) == Math.abs(res)) {
res = Math.max(res, sum);
}
}
}
return res;
}
public static void main(String[] args) {
int[] arr = {0, -8, -6, 3};
System.out.print(closestToZero(arr));
}
}
def closestToZero(arr):
# Initialize result with sum of first two elements
res = arr[0] + arr[1]
# Check all pairs
for i in range(len(arr) - 1):
for j in range(i + 1, len(arr)):
sum = arr[i] + arr[j]
if abs(sum) < abs(res):
res = sum
elif abs(sum) == abs(res):
res = max(res, sum)
return res
if __name__ == '__main__':
arr = [0, -8, -6, 3]
print(closestToZero(arr))
using System;
class GFG {
static int closestToZero(int[] arr) {
// Initialize the result with the sum
// of the first two elements
int res = arr[0] + arr[1];
// Consider every pair, find its sum and
// update result if we get a smaller value
for (int i = 0; i < arr.Length - 1; i++) {
for (int j = i + 1; j < arr.Length; j++) {
int sum = arr[i] + arr[j];
if (Math.Abs(sum) < Math.Abs(res)) {
res = sum;
}
else if (Math.Abs(sum) == Math.Abs(res)) {
res = Math.Max(res, sum);
}
}
}
return res;
}
static void Main() {
int[] arr = {0, -8, -6, 3};
Console.Write(closestToZero(arr));
}
}
function closestToZero(arr) {
// Initialize result with sum of first two elements
let res = arr[0] + arr[1];
// Check all pairs
for (let i = 0; i < arr.length - 1; i++) {
for (let j = i + 1; j < arr.length; j++) {
let sum = arr[i] + arr[j];
if (Math.abs(sum) < Math.abs(res)) {
res = sum;
}
else if (Math.abs(sum) == Math.abs(res)) {
res = Math.max(res, sum);
}
}
}
return res;
}
let arr = [0, -8, -6, 3];
console.log(closestToZero(arr));
Output
3
[Better Approach] Using Sorting + Binary Search - O(nlog(n)) Time and O(1) Space
The idea is to find the pair whose sum is closest to zero by sorting the array and using binary search for efficient lookup. For each element, we search for its closest complement using binary search, updating the closest sum found so far. If an exact zero sum is found, we return immediately.
Steps to implement the above idea:
- Sort the array to enable binary search.
- Iterate through each element and fix it as the first element of the pair.
- Use binary search to find the closest second element.
- Update the closest sum if the current pair gives a smaller absolute sum.
- Return 0 if an exact zero sum pair is found.
- Return the closest sum after checking all pairs.
#include <iostream>
#include <vector>
#include <algorithm>
#include <climits>
#include <cmath>
using namespace std;
int closestToZero(vector<int>& arr) {
sort(arr.begin(), arr.end());
int n = arr.size();
// Variable to store the closest sum
int res = INT_MAX;
// Iterate over the array
for (int i = 0; i < n; i++) {
// Consider current element as first
// element of the pair and find the
// other element using binary search
int x = arr[i];
int left = i + 1, right = n - 1;
while (left <= right) {
int mid = (left + right) / 2;
int curr = arr[mid] + x;
// If exact pair is found
if (curr == 0) {
return 0;
}
// Update res if the current pair is closer
if (abs(curr) < abs(res)) {
res = curr;
}
else if (abs(curr) == abs(res)) {
res = max(res, curr);
}
// If current is smaller than 0,
// go to right side. Else on the
// left side.
if (curr < 0) {
left = mid + 1;
} else {
right = mid - 1;
}
}
}
return res;
}
int main() {
vector<int> arr = {0, -8, -6, 3};
cout << closestToZero(arr);
return 0;
}
import java.util.*;
class GFG {
static int closestToZero(int[] arr) {
Arrays.sort(arr);
int n = arr.length;
// Variable to store the closest sum
int res = Integer.MAX_VALUE;
// Iterate over the array
for (int i = 0; i < n; i++) {
// Consider current element as first
// element of the pair and find the
// other element using binary search
int x = arr[i];
int left = i + 1, right = n - 1;
while (left <= right) {
int mid = (left + right) / 2;
int curr = arr[mid] + x;
// If exact pair is found
if (curr == 0) {
return 0;
}
// Update res if the current pair is closer
if (Math.abs(curr) < Math.abs(res)) {
res = curr;
}
else if (Math.abs(curr) == Math.abs(res)) {
res = Math.max(res, curr);
}
// If current is smaller than 0,
// go to right side. Else on the
// left side.
if (curr < 0) {
left = mid + 1;
} else {
right = mid - 1;
}
}
}
return res;
}
public static void main(String[] args) {
int[] arr = {0, -8, -6, 3};
System.out.print(closestToZero(arr));
}
}
from typing import List
import sys
def closestToZero(arr: List[int]) -> int:
arr.sort()
n = len(arr)
# Variable to store the closest sum
res = sys.maxsize
# Iterate over the array
for i in range(n):
# Consider current element as first
# element of the pair and find the
# other element using binary search
x = arr[i]
left = i + 1
right = n - 1
while left <= right:
mid = (left + right) // 2
curr = arr[mid] + x
# If exact pair is found
if curr == 0:
return 0
# Update res if the current pair is closer
if abs(curr) < abs(res):
res = curr
elif abs(curr) == abs(res):
res = max(res, curr)
# If current is smaller than 0,
# go to right side. Else on the
# left side.
if curr < 0:
left = mid + 1
else:
right = mid - 1
return res
def main():
arr = [0, -8, -6, 3]
print(closestToZero(arr))
if __name__ == "__main__":
main()
using System;
class GFG {
static int closestToZero(int[] arr) {
Array.Sort(arr);
int n = arr.Length;
// Variable to store the closest sum
int res = int.MaxValue;
// Iterate over the array
for (int i = 0; i < n; i++) {
// Consider current element as first
// element of the pair and find the
// other element using binary search
int x = arr[i];
int left = i + 1, right = n - 1;
while (left <= right) {
int mid = (left + right) / 2;
int curr = arr[mid] + x;
// If exact pair is found
if (curr == 0) {
return 0;
}
// Update res if the current pair is closer
if (Math.Abs(curr) < Math.Abs(res)) {
res = curr;
}
else if (Math.Abs(curr) == Math.Abs(res)) {
res = Math.Max(res, curr);
}
// If current is smaller than 0,
// go to right side. Else on the
// left side.
if (curr < 0) {
left = mid + 1;
} else {
right = mid - 1;
}
}
}
return res;
}
static void Main() {
int[] arr = {0, -8, -6, 3};
Console.Write(closestToZero(arr));
}
}
function closestToZero(arr) {
arr.sort((a, b) => a - b);
let n = arr.length;
// Variable to store the closest sum
let res = Number.MAX_SAFE_INTEGER;
// Iterate over the array
for (let i = 0; i < n; i++) {
// Consider current element as first
// element of the pair and find the
// other element using binary search
let x = arr[i];
let left = i + 1, right = n - 1;
while (left <= right) {
let mid = Math.floor((left + right) / 2);
let curr = arr[mid] + x;
// If exact pair is found
if (curr === 0) {
return 0;
}
// Update res if the current pair is closer
if (Math.abs(curr) < Math.abs(res)) {
res = curr;
} else if (Math.abs(curr) === Math.abs(res)) {
res = Math.max(res, curr);
}
// If current is smaller than 0,
// go to right side. Else on the
// left side.
if (curr < 0) {
left = mid + 1;
} else {
right = mid - 1;
}
}
}
return res;
}
function main() {
let arr = [0, -8, -6, 3];
console.log(closestToZero(arr));
}
main();
Output
3
[Expected Approach] Using Sorting + Two Pointer - O(nlog(n)) Time and O(1) Space
The idea is to sort the array first and use two pointers, one at the leftmost (smallest) and the other at the rightmost (largest) element. We calculate their sum and check if it's closer to zero than our current best sum. If we find a sum of zero, we return immediately. Otherwise, we adjust the pointers based on whether the sum is positive (move right pointer left) or negative (move left pointer right).
Steps to implement the above idea:
- Sort the array in ascending order.
- Initialize two pointers: one at the start and one at the end.
- Initialize variables to store the closest sum and its absolute difference.
- Iterate while left pointer is less than right pointer.
- Update the closest sum if the current sum is closer to zero.
- Move the left pointer right if the sum is negative; else, move the right pointer left.
#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
using namespace std;
int closestToZero(vector<int>& arr) {
// Sorting the vector in ascending order
sort(arr.begin(), arr.end());
int i = 0, j = arr.size() - 1;
// Initializing sum with the first
// and last elements
int sum = arr[i] + arr[j];
// Initializing the result with
// the absolute value of the initial sum
int diff = abs(sum);
while (i < j) {
// If we have zero sum, there's no
// result better. Hence, we return
if (arr[i] + arr[j] == 0)
return 0;
// If we get a better result, we update the difference
if (abs(arr[i] + arr[j]) < abs(diff)) {
diff = abs(arr[i] + arr[j]);
sum = arr[i] + arr[j];
} else if (abs(arr[i] + arr[j]) == abs(diff)) {
// If there are multiple pairs with the
// same minimum absolute difference,
// return the pair with the larger sum
sum = max(sum, arr[i] + arr[j]);
}
// If the current sum is greater than
// zero, we search for a smaller sum
if (arr[i] + arr[j] > 0)
j--;
// Else, we search for a larger sum
else
i++;
}
return sum;
}
// Driver Code
int main() {
vector<int> arr = {0, -8, -6, 3};
cout << closestToZero(arr) << endl;
return 0;
}
import java.util.*;
class GFG {
static int closestToZero(int[] arr) {
// Sorting the vector in ascending order
Arrays.sort(arr);
int i = 0, j = arr.length - 1;
// Initializing sum with the first
// and last elements
int sum = arr[i] + arr[j];
// Initializing the result with
// the absolute value of the initial sum
int diff = Math.abs(sum);
while (i < j) {
// If we have zero sum, there's no
// result better. Hence, we return
if (arr[i] + arr[j] == 0)
return 0;
// If we get a better result, we update the difference
if (Math.abs(arr[i] + arr[j]) < Math.abs(diff)) {
diff = Math.abs(arr[i] + arr[j]);
sum = arr[i] + arr[j];
} else if (Math.abs(arr[i] + arr[j]) == Math.abs(diff)) {
// If there are multiple pairs with the
// same minimum absolute difference,
// return the pair with the larger sum
sum = Math.max(sum, arr[i] + arr[j]);
}
// If the current sum is greater than
// zero, we search for a smaller sum
if (arr[i] + arr[j] > 0)
j--;
// Else, we search for a larger sum
else
i++;
}
return sum;
}
public static void main(String[] args) {
int[] arr = {0, -8, -6, 3};
System.out.println(closestToZero(arr));
}
}
from typing import List
def closestToZero(arr: List[int]):
# Sorting the vector in ascending order
arr.sort()
i = 0
j = len(arr) - 1
# Initializing sum with the first
# and last elements
sum = arr[i] + arr[j]
# Initializing the result with
# the absolute value of the initial sum
diff = abs(sum)
while i < j:
# If we have zero sum, there's no
# result better. Hence, we return
if arr[i] + arr[j] == 0:
return 0
# If we get a better result, we update the difference
if abs(arr[i] + arr[j]) < abs(diff):
diff = abs(arr[i] + arr[j])
sum = arr[i] + arr[j]
elif abs(arr[i] + arr[j]) == abs(diff):
# If there are multiple pairs with the
# same minimum absolute difference,
# return the pair with the larger sum
sum = max(sum, arr[i] + arr[j])
# If the current sum is greater than
# zero, we search for a smaller sum
if arr[i] + arr[j] > 0:
j-=1
# Else, we search for a larger sum
else:
i+=1
return sum
# Driver Code
arr = [0, -8, -6, 3]
print(closestToZero(arr))
using System;
class GFG {
static int closestToZero(int[] arr) {
// Sorting the vector in ascending order
Array.Sort(arr);
int i = 0, j = arr.Length - 1;
// Initializing sum with the first
// and last elements
int sum = arr[i] + arr[j];
// Initializing the result with
// the absolute value of the initial sum
int diff = Math.Abs(sum);
while (i < j) {
// If we have zero sum, there's no
// result better. Hence, we return
if (arr[i] + arr[j] == 0)
return 0;
// If we get a better result, we update the difference
if (Math.Abs(arr[i] + arr[j]) < Math.Abs(diff)) {
diff = Math.Abs(arr[i] + arr[j]);
sum = arr[i] + arr[j];
} else if (Math.Abs(arr[i] + arr[j]) == Math.Abs(diff)) {
// If there are multiple pairs with the
// same minimum absolute difference,
// return the pair with the larger sum
sum = Math.Max(sum, arr[i] + arr[j]);
}
// If the current sum is greater than
// zero, we search for a smaller sum
if (arr[i] + arr[j] > 0)
j--;
// Else, we search for a larger sum
else
i++;
}
return sum;
}
static void Main() {
int[] arr = {0, -8, -6, 3};
Console.WriteLine(closestToZero(arr));
}
}
function closestToZero(arr) {
// Sorting the vector in ascending order
arr.sort((a, b) => a - b);
let i = 0, j = arr.length - 1;
// Initializing sum with the first
// and last elements
let sum = arr[i] + arr[j];
// Initializing the result with
// the absolute value of the initial sum
let diff = Math.abs(sum);
while (i < j) {
// If we have zero sum, there's no
// result better. Hence, we return
if (arr[i] + arr[j] === 0)
return 0;
// If we get a better result, we update the difference
if (Math.abs(arr[i] + arr[j]) < Math.abs(diff)) {
diff = Math.abs(arr[i] + arr[j]);
sum = arr[i] + arr[j];
} else if (Math.abs(arr[i] + arr[j]) === Math.abs(diff)) {
// If there are multiple pairs with the
// same minimum absolute difference,
// return the pair with the larger sum
sum = Math.max(sum, arr[i] + arr[j]);
}
// If the current sum is greater than
// zero, we search for a smaller sum
if (arr[i] + arr[j] > 0)
j--;
// Else, we search for a larger sum
else
i++;
}
return sum;
}
// Driver Code
let arr = [0, -8, -6, 3];
console.log(closestToZero(arr));
Output
3