Two Sum Problems - 4+ ways to solve.
Tags: leetcode, faang, programming, beginners
Published: 2022-02-22 02:50:40

<mark>Here is the updated and latest one, which explains everything clearly. Could you please check this</mark> - [https://www.ggorantala.dev/two-sum/](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](https://leetcode.com/problems/two-sum/).

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:**

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

Output: [2, 7] // (because nums[0] + nums[1] == 9, we return [2, 7])
```

**Example 02:**

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

Output: [2, 4]
```

**Example 03:**

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

Output: [3, 3]
```

## 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 –

```javascript
X + Y = 10   =>   Y = ( 10 - X )
```

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).

```java
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");
  }
}
```

## 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!

```java
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");
  }
}
```

## 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.

```java
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");
  }
}
```

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

```java
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];
  }
}
```

## 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.

```java
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};
  }
}
```

## 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](https://www.educative.io/courses/bit-manipulation?aff=xjzd).