Leetcode: Two Sum

Leetcode: Two Sum

·

6 min read

The Problem

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 <= 104
-109 <= nums[i] <= 109
-109 <= target <= 109
Only one valid answer exists.

Follow-up: Can you come up with an algorithm that is less than O(n2) time complexity?

Hint 1.

A really brute force way would be to search for all possible pairs of numbers but that would be too slow. Again, it's best to try out brute force solutions for just for completeness. It is from these brute force solutions that you can come up with optimizations.

Hint 2. So, if we fix one of the numbers, say x , we have to scan the entire array to find the next number y which is value - x where value is the input parameter. Can we change our array somehow so that this search becomes faster?

Hint 3. The second train of thought is, without changing the array, can we use additional space somehow? Like maybe a hash map to speed up the search?

My Thought Process

In an array of just two items, this would be easy. If the two numbers add up to the target value, return true. Otherwise, return false. But since nums can include a variable number of integers, we have to loop through the available numbers in the array to see if any two of them could be added together to return the target value.

Looking at Hint 2, we can see that there are instances where the values in the array may include numbers higher than the target value. At the time of solving this problem, I hadn't considered negative integers, so I wrote out a line that would remove those higher numbers from the array. Beyond that, I couldn't think of a way to further simplify the array.

My initial attempt looked for a way to cycle through the numbers in the array sequentially to find an answer. In the back of my mind, I did have the secondary unsolved issue of numbers that could add up to the target value, but were not ordered sequentially. For example a+b!=target, but a+c=target. But nonetheless, this is good enough an attempt to form an initial line of code before looking at the solution. Remember that you do not have to come to an answer before looking up the solution. You can acknowledge where your code is weak, but try to get as close as you can. This initial attempt is all you need before proceeding to the answer.

My Attempt

Two Sum Problem

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number[]}
 */
var twoSum = function(nums, target) {
    let x=0;
//this line is supposed to remove any element from the array that exceeds the target value.
    while(nums[x]<=nums.length) {
        if(nums[x]>target) {
            nums.shift();
            x++;
        }
    }
//this line adds two sequential elements together to check if they equal the target value and return those two target values, otherwise increment x.
    while(nums[x]<=nums.length){
        if(nums[x]+nums[x+1]==target){
            return nums[x],nums[x+1]
        } else {
            x++;
        }
    }
};

The Solution

So, looking at the solution, it turns out that there are several tools that I did not have that were needed to solve the problem. While I was familiar with the for loop, it had been several months since I had used it, so it had largely left my memory. The remaining tools are completely new to me, but this is where googling each concept to see what they do is useful. Here is a list of tools needed to solve this problem:

  1. arrays

  2. for loop

  3. map

  4. has

  5. get

  6. set

In its simplest form, this is an algebraic problem. We have a target value, an initial value, and a variable. As an example, if we're solving for 4 + (x) = 6, where 4 is the initial value, (x) is the variable, and 6 is the target value, to solve for (x), we subtract 4 from both sides to get (x) = 6 - 4. This will be the general strategy we employ to get the answer, but to iterate through the array, we must first map each value to an index so we can later recall it to see if it satisfies the condition using "has" and "get". If the element pairings do not satisfy the condition, we map it to the "map" variable using the (value, index) pairing. This creates a list of values for the function to refer to until a satisfying match is found. If we had an array of [3, 4, 2, 1], with target=6, the map function would create a list of {3:0, 4:1, 2:2} before terminating because the conditions were satisfied upon finding 4+2=6, and no further iteration is needed because the problem explicitly stated that each input would have exactly one solution.

So here is the resulting code:

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number[]}
 */
var twoSum = function(nums, target) {
    //create a new map variable
    let map= new Map();
    //iterate through the array using the for loop
    for (let i=0; i<nums.length; i++) {
        //create a variable for the initial value
        let num1=nums[i];
        //create a variable for the second value which satisfies the condition num1+num2=target by solving for the second value, thus creating num2=target-num1
        let num2=target-nums[i];
        //if the map has a value which satisfies the condition
        if(map.has(num2)) {
            //return the two values
            return[i, map.get(num2)];
            //otherwise, set the initial value and its index to the map variable
        } map.set(num1, i);
    }
};

The Takeaway

The goal of this exercise isn't to memorize the answer, but to logically arrive at the solution given the problem parameters.

So when we revisit this question in a week, our thought process shouldn't be "What was step 1 in the solution?", but instead, "What is the question asking for, and what tools should I prepare to answer this problem?"

All of the tools we need come from our ability to use a for loop, map the results, and retrieve them. It's good practice to set a variable for each component you'll use in your solution. So you know you'll need to make a map variable, an initial value variable (num1), and a final value variable (num2) that satisfies the condition num2=target-num1. We can set a map variable without requiring any prior conditions, so do that right away. let map = new Map();

But num1 requires an additional condition that will allow us to loop through all possible values of nums[i]. So before defining num1, we should first set up a for loop, for (let i=0; i<nums.length; i++) and then define num1, after which we have the building blocks to define num2 as our final variable. Then set up an if statement that will return our desired solution. Finally, we should tell the function what to do if all of the above produces no satisfying result: set the current value and its index to the map variable, map.set(num1, i); Always think of the strategy first before reaching for the solution. Define each component separately. And tell the function what to do if everything fails.

Wordle 285 6/6

⬛⬛⬛⬛⬛

⬛🟨⬛🟨⬛

⬛⬛⬛⬛⬛

⬛⬛🟨🟨⬛

🟨🟩⬛🟩🟩

🟩🟩🟩🟩🟩

I hate double letters in Wordle puzzles.

Did you find this article valuable?

Support Roy Jang by becoming a sponsor. Any amount is appreciated!