Skip to content

Commit

Permalink
Solve 1 - Two Sum (#6)
Browse files Browse the repository at this point in the history
  • Loading branch information
terenceponce committed Dec 16, 2023
1 parent 423a0af commit 531cbef
Show file tree
Hide file tree
Showing 6 changed files with 193 additions and 0 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,7 @@
[![codecov](https://codecov.io/gh/terenceponce/leetcode/graph/badge.svg?token=i7gC0Uuurl)](https://codecov.io/gh/terenceponce/leetcode)

This is a monorepo containing my solutions to LeetCode problems written in various languages.

## List of Problems/Solutions

- 1 - Two Sum - [Notes](notes/0001_two_sum.md) | [Elixir](elixir/lib/solutions/0001_two_sum/two_sum.ex) | [Ruby](ruby/lib/solutions/0001_two_sum/two_sum.rb)
19 changes: 19 additions & 0 deletions elixir/lib/solutions/0001_two_sum/two_sum.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
defmodule LeetCode.Solutions.TwoSum do
@moduledoc false

@spec call(nums :: [integer], target :: integer) :: [integer]
def call(nums, target) do
nums
|> Enum.with_index()
|> Enum.reduce({%{}, []}, fn {num, index}, {map, result} ->
case Map.get(map, target - num) do
nil ->
{Map.put(map, num, index), result}

match ->
{map, [match, index]}
end
end)
|> elem(1)
end
end
17 changes: 17 additions & 0 deletions elixir/test/solutions/0001_two_sum/two_sum_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
defmodule LeetCode.Solutions.TwoSumTest do
use ExUnit.Case, async: true

alias LeetCode.Solutions.TwoSum

test "Case 1 works" do
assert TwoSum.call([2, 7, 11, 15], 9) == [0, 1]
end

test "Case 2 works" do
assert TwoSum.call([3, 2, 4], 6) == [1, 2]
end

test "Case 3 works" do
assert TwoSum.call([3, 3], 6) == [0, 1]
end
end
122 changes: 122 additions & 0 deletions notes/0001_two_sum.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
# Two Sum

**Link to Problem**: https://leetcode.com/problems/two-sum

## Solutions

- [Elixir](../elixir/lib/solutions/0001_two_sum/two_sum.ex)
- [Ruby](../ruby/lib/solutions/0001_two_sum/two_sum.rb)

## Description

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.

## Examples

### 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]
```

## Solution

This is my first ever LeetCode problem and I usually suck at algorithms, so this took me a long time to get.

For people like me, the first solution I thought of was to iterate through each element in the list,
compare it with all the other elements in the list, and try to add both elements to see if it matches
the target.

Unfortunately, while this does work, it is very slow because you have to go through the list multiple
times in order to get the result.

The optimal solution is to use a Hash Map which makes it possible to get the same answer while only
going through the list once.

Before we dive into the solution itself, I'd like to discuss something else first.

One thing that I had to realize was that there was another way to figure out what elements it would
take to reach the target. The obvious solution is to perform addition on all the elements until we
get a sum that matches the target.

Another way is to do it backwards and perform subtraction instead. We take the current element and
subtract that from the target. From there, we try to figure out if there is an element that matches
the difference.

So how do we do that exactly? By creating a new variable and storing all the value and index of
the current element if it doesn't satisfy the condition to match the target. In this case, we create
a Hash Map (or Map in Elixir) since it allows us to store both value and index.

In the case of Example 2, it would look like this:

```
[3, 2, 4]
^
|
we are here
```

Since the target is `6`, we will do `6 - 3` which is `3`. What we then do is look at our map
to see if there is an element that has `3` as the value.

At this point, our map is still empty, so there won't be any matches. The conclusion for this
element is that we will skip it and go to the next one. However, we will also add this element
into the map before we move to the next one:

```
{3: 0}
```

We put the value as the key, so we can use it for lookups and the index as the value, so we can get it later.

After we stored the first element into the map, we will go to the next element:

```
[3, 2, 4]
^
|
we are here
```

At this point, we will try to do `6 - 2` which is `4`. We then look at the map to see if we
have any matches.

Since we only have `3` inside the map, there won't be any matches. So we repeat what we did
in the previous element which is to add the current element to the map and move on to the next element:

```
{3: 0, 2: 1}
```

Afterwards, we go to the last element:

```
[3, 2, 4]
^
|
we are here
```

Obviously, we will try to do `6 - 4` which will result to `2`. If we do `Map.get(map, target - num)`,
we will get `2` which has the value of `1`. From there, we should now be able to determine that the
indices `[1, 2]` are the answer.
13 changes: 13 additions & 0 deletions ruby/lib/solutions/0001_two_sum/two_sum.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# frozen_string_literal: true

def two_sum(nums, target)
hash = {}

nums.each_with_index do |num, index|
diff = target - num

return [hash[diff], index] if hash[diff]

hash[num] = index
end
end
18 changes: 18 additions & 0 deletions ruby/test/solutions/0001_two_sum/two_sum_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# frozen_string_literal: true

require 'test_helper'
require_relative '../../../lib/solutions/0001_two_sum/two_sum'

class TwoSumTest < Minitest::Test
def test_case_1_works
assert_equal [0, 1], two_sum([2, 7, 11, 15], 9)
end

def test_case_2_works
assert_equal [1, 2], two_sum([3, 2, 4], 6)
end

def test_case_3_works
assert_equal [0, 1], two_sum([3, 3], 6)
end
end

0 comments on commit 531cbef

Please sign in to comment.