DEV Community

Cover image for Two Sum Problems - 4+ ways to solve.
Gopi Gorantala
Gopi Gorantala

Posted on • Edited on

Two Sum Problems - 4+ ways to solve.

Here is the updated and latest one, which explains everything clearly. Could you please check this - https://www.ggorantala.dev/two-sum/

Introduction

Two Sum problem is a classic problem and this has been listed first as one of the basic questions one has to solve when prepping for coding interviews. Leetcode, one of the largest tech communities with hundreds of thousands of active users to participate and solve coding problems listed this as the first problem in their curriculum – the Leetcode TwoSum Problem.

Let us discuss the TwoSum algorithm of a given input. This is one of the most popular questions asked in coding interviews.

Companies that have asked this in their coding interview are Facebook, Amazon, Apple, Netflix, Google, Microsoft, Adobe, and many more top tech companies.

Problem Statement

In the TwoSum Problem given an array of integers, nums and an integer, return the two numbers such that they add up to the target. You may assume that each input would have exactly one solution, and you may not use the same element twice. You can return the answer in order.

Example 01:

Input: nums = [2, 7, 11, 15], target = 9

Output: [2, 7] // (because nums[0] + nums[1] == 9, we return [2, 7])
Enter fullscreen mode Exit fullscreen mode

Example 02:

Input: nums = [3, 2, 4], target = 6

Output: [2, 4]
Enter fullscreen mode Exit fullscreen mode

Example 03:

Input: nums = [3, 3], target = 6

Output: [3, 3]
Enter fullscreen mode Exit fullscreen mode

Thought Process

First Way

Let us consider the array as {3, 5, -4, 8, 11, 1, -1, 6}, and target = 10.

Considering unique integers, you can use the Set interface or Map in Java.

Let X, Y below the two numbers, the question clearly states that two numbers add up to the target. We can represent this mathematically by –

X + Y = 10   =>   Y = ( 10 - X )
Enter fullscreen mode Exit fullscreen mode

So, when iterating the elements you get X value and check if (10 - X) which is Y present in the HashTable, isn’t that easy to find? also, this is a constant lookup time.

Time complexity: O(n) is the worst case, where we need to iterate all the elements.

Space complexity is O(n), storing elements is HashTable.

Second way:

Any optimizations to above?

Can we solve this in a more optimal, with no extra space?

Yes, first we sort the entire array, and then we use the two pointers left, right to find the target sum.

  1. Sorting takes O(NlogN) and finding the sum takes O(n).

  2. Overall the time it takes is O(NlogN) and space O(1).
    We look at this two-pointer approach at the last, let us see some of the options we can solve this.

Important Note: We recommend you run through all the solutions shown here. Don’t jump to the optimal solutions directly as they might help you but won’t improve your thought process at real coding interviews.

If you want to get good with algorithms and problem-solving and improve your understanding of problems and ways to handle them, then you need to see how solutions are implemented in all possible ways.

Solution

Approach 01: Brute Force

The brute force approach is simple, loop through each element x and find another value that equals (target - x).

import java.util.Arrays;

public class TwoSum {
  public static void main(String[] args) {
    int[] input = {2, 7, 11, 15};
    int targetSum = 18;
    System.out.println(Arrays.toString(twoSum(input, targetSum)));
  }

  public static int[] twoSum(int[] nums, int targetSum) {
    for (int i = 0; i < nums.length; i++) {
      for (int j = i + 1; j < nums.length; j++) {
        if (nums[j] == targetSum - nums[i]) {
          return new int[]{i, j};
        }
      }
    }
    throw new IllegalArgumentException("No two sum solution");
  }
}
Enter fullscreen mode Exit fullscreen mode

Complexity Analysis

Time complexity: O(n^2), for each element, we try to find its complement by looping through the rest of the array which takes O(n) time. Therefore, the time complexity is O(n^2), where n is the length of the elements present in the array.

Space complexity: O(1), as no extra space is utilized.

Approach 02: Two-Pass HashTable

We need a more efficient way to check if the complement exists in the array to improve our run time complexity.

If the complement exists, we need to look up its index. What is the best way to maintain a mapping of each element in the array to its index?

We reduce the lookup time from O(n) to O(1) by trading space for speed. A hash table is built exactly for this purpose, it supports fast lookup in the next constant time.

I say “near” because a look-up could degenerate to O(n) time if a collision occurred. But look up in hash table should be amortized O(1) time as long as the hash function was chosen carefully.

A simple implementation uses two iterations. In the first iteration, we add each element’s value and its index to the table.

Then, in the second iteration, we check if each element’s complement(target - nums[i]) exists in the table. Beware that the complement must not be nums[i] itself!

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

public class TwoSum {
  public static void main(String[] args) {
    int[] input = {2, 7, 11, 15};
    int targetSum = 18;
    System.out.println(Arrays.toString(twoSum(input, targetSum)));
  }

  public static int[] twoSum(int[] nums, int target) {
    Map<Integer, Integer> map = new HashMap<>();

    for (int i = 0; i < nums.length; i++) {
      map.put(nums[i], i);
    }

    for (int i = 0; i < nums.length; i++) {
      int complement = target - nums[i];
      if (map.containsKey(complement) && map.get(complement) != i) {
        return new int[]{i, map.get(complement)};
      }
    }

    throw new IllegalArgumentException("No two sum solution");
  }
}
Enter fullscreen mode Exit fullscreen mode

Complexity Analysis

Time complexity: O(n) We traverse the list containing n elements exactly twice. Since the hash table reduces the look-up time to O(1), the time complexity is O(n).

Space complexity: O(n) The extra space required depends on the number of items stored in the hash table, which stores exactly n elements.

Approach 03: One-Pass HashTable

It turns out we can do it in one pass. While we iterate and insert elements into the table, we also check if the current element’s complement already exists in the table. If it exists, we have found a solution and returned it immediately.

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

public class TwoSum {
  public static void main(String[] args) {
    int[] input = {2, 7, 11, 15};
    int targetSum = 18;
    System.out.println(Arrays.toString(twoSum(input, targetSum)));
  }

  public static int[] twoSum(int[] nums, int target) {
    Map<Integer, Integer> map = new HashMap<>();

    for (int i = 0; i < nums.length; i++) {
      int potentialDifference = target - nums[i];
      if (map.containsKey(potentialDifference)) {
        return new int[]{map.get(potentialDifference), i};
      }
      map.put(nums[i], i);
    }
    throw new IllegalArgumentException("No two sum solution");
  }
}
Enter fullscreen mode Exit fullscreen mode

So, let’s see how we can achieve the same using the Set interface.

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

public class TwoSum {
  public static void main(String[] args) {
    int[] input = {2, 7, 11, 15};
    int targetSum = 18;
    System.out.println(Arrays.toString(twoSum(input, targetSum)));
  }

  public static int[] twoSum(int[] array, int targetSum) {
    Set<Integer> set = new HashSet<>();

    for (int num : array) {
      int potentialDiff = targetSum - num;
      if (set.contains(potentialDiff)) {
        return new int[]{potentialDiff, num};
      }
      set.add(num);
    }
    // Write your code here.
    return new int[0];
  }
}
Enter fullscreen mode Exit fullscreen mode

Complexity Analysis

Time complexity: O(n) We traverse the list containing n elements only ones, each lookup in the table only costs O(1) time.

Space complexity: O(n) The extra space required depends on the number of items stored in the table, which stores at most n elements.

Approach 04: Two Pointer

First, sort the array and then use the two-pointer left, right and iterate them over the array.

import java.util.Arrays;

public class TwoSum {
  public static void main(String[] args) {
    int[] input = {2, 7, 11, 15};
    int targetSum = 18;
    System.out.println(Arrays.toString(twoSum(input, targetSum)));
  }

  public static int[] twoSum(int[] array, int targetSum) {
    Arrays.sort(array);

    int left = 0;
    int right = array.length - 1;

    while (left <= right) {
      int s = array[left] + array[right];

      if (s == targetSum) {
        return new int[]{array[left], array[right]};
      } else if (s < targetSum) {
        left++;
      } else if (s > targetSum) {
        right--;
      }
    }
    return new int[]{-1, -1};
  }
}
Enter fullscreen mode Exit fullscreen mode

Complexity Analysis

Time complexity: O(NlogN), Sorting takes O(NlogN), and running through a loop takes O(n) time. So overall time complexity is O(NlogN).

Space Complexity: O(1) We didn't flood any data onto memory. We used variables to store temporary data which is arbitary.


Extras

If you are interested in mastering bit tricks, I've got a course that are loved by more than 100k+ programmers.

In this course, you will learn how to solve problems using bit manipulation, a powerful technique that can be used to optimize your algorithmic and problem-solving skills. The course has simple explanation with sketches, detailed step-by-step drawings, and various ways to solve it using bitwise operators.

These bit-tricks could help in competitive programming and coding interviews in running algorithms mostly in O(1) time.

This is one of the most important/critical topics when someone starts preparing for coding interviews for FAANG(Facebook, Amazon, Apple, Netflix, and Google) companies.

To kick things off, you’ll start by learning about the number system and how it’s represented. Then you’ll move on to learn about the six different bitwise operators: AND, OR, NOT, XOR, and bit shifting. Throughout, you will get tons of hands-on experience working through practice problems to help sharpen your understanding.

By the time you’ve completed this course, you will be able to solve problems faster with greater efficiency!! 🤩

Link to my course: Master Bit Manipulation for Coding Interviews.

Top comments (3)

Collapse
 
ronozoro profile image
Mostafa Mohamed

That 4th approach is kinda stupid, the method should return the indexes not the values, you can't solve this with 2 pointers + sort arrays unless u use extra DS

Collapse
 
ggorantala profile image
Gopi Gorantala

@ronozoro - You're right, this is an old article. Here is the updated and latest one, which explains everything clearly. Could you please check this - ggorantala.dev/two-sum/

Collapse
 
ashwinshirva profile image
ashwinshirva • Edited

Excellent article. Very well written. Thank you!

In case someone is looking for video solution for this problem you can watch this:

Two Sum Video
Image description

Above video and this article made understand this problem so easily! Thank you so much!