Exploring LeetCode: Two Sum

Abi FarhanAbi Farhan
7 min read

Introduction

Two Sum is a classic coding problem that tests your ability to find a pair of numbers in an array that add up to a specific target value. This deceptively simple task requires a solid understanding of data manipulation, algorithmic thinking, and problem-solving strategies.

Problem Overview

Given an array of integers nums and an integer target, return indices of the two numbers such that they add up to 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 any order.

Example 1

Input: nums = [2,7,11,15], target = 9
Output: [0,1]
Explanation: Because nums[0] + nums[1] == 9, we return [0, 1].

Example 2

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

Example 3

Input: nums = [3,3], target = 6
Output: [0,1]

Constraints:

  • 2 <= nums.length <= 10<sup>4</sup>

  • -10<sup>9</sup> <= nums[i] <= 10<sup>9</sup>

  • -10<sup>9</sup> <= target <= 10<sup>9</sup>

  • Only one valid answer exists.

Brute Force Approach

To effectively solve the problem, it is important to have a thorough understanding of the underlying mathematical concept before proceeding with the coding process. Let's break it down step by step.

Consider the scenario where we have a current number of 2 and a target number of 11. The objective is to find another number that, when added to the current number, equals the target value. In this case, the number we need to find is 9.

Based on our initial analysis, we can establish a simple formula: target = current number + number to find.

The key idea here is that although we only know the target and the current number, we can deduce the number to find by subtracting the current number from the target: number to find = target - current number.

Approaching problem-solving with a solid understanding of the underlying concepts and formulating a solution conceptually before diving into the coding phase is crucial.

With a firm grasp of the fundamental concept, we can confidently proceed to implement the solution.

Below is a snippet of code that demonstrates the implementation:

const findTwoSum = function(nums, target) {

    for(let i = 0; i < nums.length; i++) {
        const numToFind = target - nums[i]

        for (let j = i + 1; j < nums.length; j++) {
            if (nums[j] === numToFind) {
                return [i, j]
            }
        }
    }

    return null;
}

Let's analyze the code step by step:

  1. The code starts by iterating through each element in the array to determine the current number. This is achieved using a loop that traverses the array.

  2. Once we have the current number, we move on to defining the target number. We do this by assigning a variable called "numToFind" to represent the target value.

  3. Following the target definition, we encounter a nested loop within the initial loop. This nested loop is responsible for searching the array to find a number that matches the value stored in "numToFind."

By employing this logical approach, we systematically iterate through the array to identify the current number, establish the target number, and conduct a nested iteration to find a matching number. Ultimately, this process enables us to identify a pair of numbers that fulfill the given condition.

Optimal Approach

Upon analyzing the brute force approach, it becomes apparent that the code complexity remains quadratic due to the presence of a nested loop. It is essential to optimize this solution. Let's engage in a brainstorming session to explore potential improvements.

  • The underlying rationale for incorporating two loops lies in the necessity of simultaneously tracking the current number in the outer loop and identifying the corresponding number in the inner loop to achieve the desired match.

  • By leveraging a hashmap or similar data structure, we can avoid the need for nested loops. Instead, we can store the current numbers as keys and their indices as values. This eliminates the necessity for a second loop and allows us to find matching numbers in a single pass. This optimized approach improves code efficiency and reduces time complexity. Exploring alternative strategies is crucial for optimizing code and achieving optimal performance.

  • We efficiently track the current numbers to find and their corresponding indices by leveraging a hashmap or similar data structure. This approach eliminates the need for an additional loop and simplifies the retrieval of indices.

Below is a snippet of code that demonstrates the implementation:

var twoSum = function(nums, target) {

   var mapsArray = {}
for(let i = 0; i < nums.length; i++){
    const currentValue = mapsArray[nums[i]]
    if(currentValue >= 0){
        return [currentValue, i ]
    } else {
        let numberToFind = target - nums[i]
        mapsArray[numberToFind] = i
    }
}

return null
};

Test Cases

To strengthen your problem-solving skills, it is beneficial to analyze and practice with various test cases.

  1. Input: nums = [2, 7, 11, 15], target = 9 Output: [0, 1] Explanation: The sum of nums[0] and nums[1] is equal to the target (9).

  2. Input: nums = [3, 2, 4], target = 6 Output: [1, 2] Explanation: The sum of nums[1] and nums[2] is equal to the target (6).

  3. Input: nums = [0, 4, 3, 0], target = 0 Output: [0, 3] Explanation: The sum of nums[0] and nums[3] is equal to the target (0).

  4. Input: nums = [-1, -2, -3, -4, -5], target = -8 Output: [2, 4] Explanation: The sum of nums[2] and nums[4] is equal to the target (-8).

  5. Input: nums = [1, 2, 3, 4, 5], target = 10 Output: [3, 4] Explanation: The sum of nums[3] and nums[4] is equal to the target (10).

  6. Input: nums = [1, 1, 1, 1], target = 2 Output: [0, 1] Explanation: The sum of nums[0] and nums[1] is equal to the target (2).

  7. Input: nums = [9, 8, 7, 6, 5], target = 13 Output: [0, 4] Explanation: The sum of nums[0] and nums[4] is equal to the target (13).

  8. Input: nums = [3, 5, 2, 9, 11], target = 14 Output: [1, 4] Explanation: The sum of nums[1] and nums[4] is equal to the target (14).

  9. Input: nums = [-2, 0, 10, -5, 20], target = 15 Output: [2, 4] Explanation: The sum of nums[2] and nums[4] is equal to the target (15).

  10. Input: nums = [4, 6, 8, 2], target = 10 Output: [0, 3] Explanation: The sum of nums[0] and nums[3] is equal to the target (10).

Conclusion

The provided solutions tackle the "Two Sum" problem using different approaches. Here's a summary highlighting their key differences:

  1. Brute Force Solution:

    • This approach employs nested loops to iterate through each element in the input array and check for a pair that sums up to the target.

    • It has a time complexity of O(n^2), meaning the execution time grows quadratically with the size of the input array.

    • Since it checks all possible combinations, it does not require additional data structures, resulting in a space complexity of O(1).

  2. Optimal Solution with HashMap:

    • The optimal solution utilizes a HashMap to store previously encountered numbers and their indices.

    • It performs a single pass through the array, checking if the complement (target minus the current number) exists in the HashMap. If found, it returns the pair of indices.

    • With a time complexity of O(n), it provides a more efficient solution compared to the brute force approach, especially for large input arrays.

    • However, it requires extra space to store the HashMap, resulting in a space complexity of O(n).

Differences:

  • The brute force solution has a higher time complexity (quadratic) compared to the optimal solution (linear), making the latter more efficient for larger arrays.

  • The brute force solution compares each element with all other elements, while the optimal solution utilizes a HashMap for faster complement lookup.

  • The optimal solution trades off space complexity for improved time complexity, as it needs to store the HashMap.

In conclusion, the optimal solution with a HashMap offers a more efficient and scalable approach for the "Two Sum" problem. It leverages the HashMap's constant-time lookup to achieve linear time complexity, outperforming the brute force solution. However, it requires additional space to store the HashMap.

References

0
Subscribe to my newsletter

Read articles from Abi Farhan directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Abi Farhan
Abi Farhan

Working professionally with high passion and curiosity about Entrepreneurship, Tech, and Coffee. I am willing to work hard, learn faster, and extremely fast adaptation to new tech stacks. I have more 3 years of experience as a Software Engineer in the Industry world and academic world, I believe with my experience combined with my abilities as an Entrepreneur and Software Engineer with a deep understanding of data structure and algorithms also as strong skills for problem-solving would make me a valuable asset too much technology-oriented business seeking the talent with always hungry for knowledge and always eager to learn new things. For now, I work as Software Engineer in Aleph-Labs which develop the MyXL Ultimate app also I develop my own business Gayo Coffee Engaged in B2B and B2C. I am also Bilingual Communicator (English, Indonesia) with experience public speaker and leadership. I also experiece management project using Jira and Notion, also strong skills for teamwork including deep knowledge about Version Control System like Git.