From 5fd2a58e2cca9b443c95ba0795b7237a4fe5e656 Mon Sep 17 00:00:00 2001 From: javy99 Date: Sun, 25 May 2025 13:30:20 +0200 Subject: [PATCH] solution for two sum problem --- 1_arrays_and_hashing/3_two_sum/solution.go | 79 +++++++++++++++++++ .../3_two_sum/solution_test.go | 57 +++++++++++++ 2 files changed, 136 insertions(+) create mode 100644 1_arrays_and_hashing/3_two_sum/solution.go create mode 100644 1_arrays_and_hashing/3_two_sum/solution_test.go diff --git a/1_arrays_and_hashing/3_two_sum/solution.go b/1_arrays_and_hashing/3_two_sum/solution.go new file mode 100644 index 0000000..9030381 --- /dev/null +++ b/1_arrays_and_hashing/3_two_sum/solution.go @@ -0,0 +1,79 @@ +package twosum + +import "sort" + +// Time complexity: O(n^2) +// Space complexity: O(1) +func TwoSumBruteForce(nums []int, target int) []int { + for i := 0; i < len(nums); i++ { + for j := i + 1; j < len(nums); j++ { + if nums[i]+nums[j] == target { + return []int{i, j} + } + } + } + return nil +} + +type Pair struct { + val int + idx int +} + +// Time complexity: O(n log n) +// Space complexity: O(n) +func TwoSumSorted(nums []int, target int) []int { + pairs := make([]Pair, len(nums)) + for i, v := range nums { + pairs[i] = Pair{val: v, idx: i} + } + sort.Slice(pairs, func(i, j int) bool { + return pairs[i].val < pairs[j].val + }) + + left, right := 0, len(pairs)-1 + for left < right { + sum := pairs[left].val + pairs[right].val + if sum == target { + return []int{pairs[left].idx, pairs[right].idx} + } else if sum < target { + left++ + } else { + right-- + } + } + return nil +} + +// Time complexity: O(n) +// Space complexity: O(n) +func TwoSumMapTwoPass(nums []int, target int) []int { + // First pass: build map + m := make(map[int]int) // value -> index + for i, num := range nums { + m[num] = i + } + + // Second pass: check complements + for i, num := range nums { + complement := target - num + if j, ok := m[complement]; ok && i != j { + return []int{i, j} + } + } + return nil +} + +// Time complexity: O(n) +// Space complexity: O(n) +func TwoSumMapOnePass(nums []int, target int) []int { + m := make(map[int]int) // value -> index + for i, num := range nums { + complement := target - num + if j, ok := m[complement]; ok { + return []int{j, i} + } + m[num] = i + } + return nil +} diff --git a/1_arrays_and_hashing/3_two_sum/solution_test.go b/1_arrays_and_hashing/3_two_sum/solution_test.go new file mode 100644 index 0000000..684efb6 --- /dev/null +++ b/1_arrays_and_hashing/3_two_sum/solution_test.go @@ -0,0 +1,57 @@ +package twosum + +import ( + "reflect" + "testing" +) + +func TestTwoSum(t *testing.T) { + cases := []struct { + name string + fn func([]int, int) []int + nums []int + target int + expected []int + }{ + // TwoSumBruteForce + {"Brute Force - Valid Pair", TwoSumBruteForce, []int{2, 7, 11, 15}, 9, []int{0, 1}}, + {"Brute Force - No Pair", TwoSumBruteForce, []int{1, 2, 3}, 7, nil}, + {"Brute - Empty", TwoSumBruteForce, []int{}, 0, nil}, + {"Brute - Single Element", TwoSumBruteForce, []int{5}, 5, nil}, + {"Brute - Negative Numbers", TwoSumBruteForce, []int{-3, 4, 3, 90}, 0, []int{0, 2}}, + {"Brute - Duplicates", TwoSumBruteForce, []int{3, 3}, 6, []int{0, 1}}, + + // Sorting (Two Pointer) + {"Sorted - Valid Pair", TwoSumSorted, []int{2, 7, 11, 15}, 9, []int{0, 1}}, + {"Sorted - No Pair", TwoSumSorted, []int{1, 2, 3}, 7, nil}, + {"Sorted - Empty", TwoSumSorted, []int{}, 0, nil}, + {"Sorted - Single Element", TwoSumSorted, []int{5}, 5, nil}, + {"Sorted - Negative Numbers", TwoSumSorted, []int{-3, 4, 3, 90}, 0, []int{0, 2}}, + {"Sorted - Duplicates", TwoSumSorted, []int{3, 3}, 6, []int{0, 1}}, + + // Map Two-Pass + {"MapTwoPass - Valid Pair", TwoSumMapTwoPass, []int{2, 7, 11, 15}, 9, []int{0, 1}}, + {"MapTwoPass - No Pair", TwoSumMapTwoPass, []int{1, 2, 3}, 7, nil}, + {"MapTwoPass - Empty", TwoSumMapTwoPass, []int{}, 0, nil}, + {"MapTwoPass - Single", TwoSumMapTwoPass, []int{5}, 5, nil}, + {"MapTwoPass - Negative", TwoSumMapTwoPass, []int{-3, 4, 3, 90}, 0, []int{0, 2}}, + {"MapTwoPass - Duplicates", TwoSumMapTwoPass, []int{3, 3}, 6, []int{0, 1}}, + + // Map One-Pass + {"MapOnePass - Valid Pair", TwoSumMapOnePass, []int{2, 7, 11, 15}, 9, []int{0, 1}}, + {"MapOnePass - No Pair", TwoSumMapOnePass, []int{1, 2, 3}, 7, nil}, + {"MapOnePass - Empty", TwoSumMapOnePass, []int{}, 0, nil}, + {"MapOnePass - Single", TwoSumMapOnePass, []int{5}, 5, nil}, + {"MapOnePass - Negative", TwoSumMapOnePass, []int{-3, 4, 3, 90}, 0, []int{0, 2}}, + {"MapOnePass - Duplicates", TwoSumMapOnePass, []int{3, 3}, 6, []int{0, 1}}, + } + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + got := c.fn(c.nums, c.target) + if !reflect.DeepEqual(got, c.expected) { + t.Errorf("%s failed: expected %v, got %v", c.name, c.expected, got) + } + }) + } +}