From ed685a2d0de05af52d5b6ea5193070ec4ac37b47 Mon Sep 17 00:00:00 2001 From: Austin Gebauer Date: Tue, 9 Mar 2021 22:18:19 -0800 Subject: [PATCH 01/14] intersection_of_two_linked_lists_160: solved --- .../README.md | 68 +++++++++++++++++++ .../solution.go | 51 ++++++++++++++ .../solution_test.go | 15 ++++ 3 files changed, 134 insertions(+) create mode 100644 intersection_of_two_linked_lists_160/README.md create mode 100644 intersection_of_two_linked_lists_160/solution.go create mode 100644 intersection_of_two_linked_lists_160/solution_test.go diff --git a/intersection_of_two_linked_lists_160/README.md b/intersection_of_two_linked_lists_160/README.md new file mode 100644 index 0000000..790c5fd --- /dev/null +++ b/intersection_of_two_linked_lists_160/README.md @@ -0,0 +1,68 @@ +# 160. Intersection of Two Linked Lists + +https://leetcode.com/problems/intersection-of-two-linked-lists/ + +## Difficulty: + +Easy + +## Description + +Given the heads of two singly linked-lists headA and headB, return the node at which the two lists +intersect. If the two linked lists have no intersection at all, return null. + +For example, the following two linked lists begin to intersect at node c1: + +![](https://assets.leetcode.com/uploads/2021/03/05/160_statement.png) + +It is **guaranteed** that there are no cycles anywhere in the entire linked structure. + +Note that the linked lists must **retain their original structure** after the function returns. + +Example 1: + +![](https://assets.leetcode.com/uploads/2021/03/05/160_example_1_1.png) + +``` +Input: intersectVal = 8, listA = [4,1,8,4,5], listB = [5,6,1,8,4,5], skipA = 2, skipB = 3 +Output: Intersected at '8' +Explanation: The intersected node's value is 8 (note that this must not be 0 if the two lists intersect). +From the head of A, it reads as [4,1,8,4,5]. From the head of B, it reads as [5,6,1,8,4,5]. There +are 2 nodes before the intersected node in A; There are 3 nodes before the intersected node in B. +``` + +Example 2: + +![](https://assets.leetcode.com/uploads/2021/03/05/160_example_2.png) + +``` +Input: intersectVal = 2, listA = [1,9,1,2,4], listB = [3,2,4], skipA = 3, skipB = 1 +Output: Intersected at '2' +Explanation: The intersected node's value is 2 (note that this must not be 0 if the two lists intersect). +From the head of A, it reads as [1,9,1,2,4]. From the head of B, it reads as [3,2,4]. There are +3 nodes before the intersected node in A; There are 1 node before the intersected node in B. +``` + +Example 3: + +![](https://assets.leetcode.com/uploads/2021/03/05/160_example_3.png) + +``` +Input: intersectVal = 0, listA = [2,6,4], listB = [1,5], skipA = 3, skipB = 2 +Output: No intersection +Explanation: From the head of A, it reads as [2,6,4]. From the head of B, it reads as [1,5]. Since +the two lists do not intersect, intersectVal must be 0, while skipA and skipB can be arbitrary values. +Explanation: The two lists do not intersect, so return null. +``` + +Constraints: +- The number of nodes of listA is in the m. +- The number of nodes of listB is in the n. +- 1 <= m, n <= 3 * 104 +- 1 <= Node.val <= 105 +- 1 <= skipA <= m +- 1 <= skipB <= n +- intersectVal is 0 if listA and listB do not intersect. +- intersectVal == listA[skipA + 1] == listB[skipB + 1] if listA and listB intersect. + +Follow up: Could you write a solution that runs in O(n) time and use only O(1) memory? diff --git a/intersection_of_two_linked_lists_160/solution.go b/intersection_of_two_linked_lists_160/solution.go new file mode 100644 index 0000000..ce8bf4e --- /dev/null +++ b/intersection_of_two_linked_lists_160/solution.go @@ -0,0 +1,51 @@ +package intersection_of_two_linked_lists_160 + +import ( + "math" + + . "github.com/austingebauer/go-leetcode/structures" +) + +/** + * Definition for singly-linked list. + * type ListNode struct { + * Val int + * Next *ListNode + * } + */ +func getIntersectionNode(headA, headB *ListNode) *ListNode { + lenA, lenB := length(headA), length(headB) + + // Set itr1 to the list with the greater length + var itr1, itr2 *ListNode + if lenA > lenB { + itr1, itr2 = headA, headB + } else { + itr1, itr2 = headB, headA + } + + // Advance itr1 so that it's in step with itr2 with respect to length + distance := int(math.Abs(float64(lenA - lenB))) + for i := 0; i < distance; i++ { + itr1 = itr1.Next + } + + // Move both pointers forward until an intersection occurs or end of list + for itr1 != nil { + if itr1 == itr2 { + return itr1 + } + itr1, itr2 = itr1.Next, itr2.Next + } + + return nil +} + +func length(n *ListNode) int { + var l int + for n != nil { + l++ + n = n.Next + } + return l +} diff --git a/intersection_of_two_linked_lists_160/solution_test.go b/intersection_of_two_linked_lists_160/solution_test.go new file mode 100644 index 0000000..463f419 --- /dev/null +++ b/intersection_of_two_linked_lists_160/solution_test.go @@ -0,0 +1,15 @@ +package intersection_of_two_linked_lists_160 + +import ( + "testing" + + . "github.com/austingebauer/go-leetcode/structures" + "github.com/stretchr/testify/assert" +) + +func Test_getIntersectionNode(t *testing.T) { + intersectNode := &ListNode{Val: 8, Next: &ListNode{Val: 4, Next: &ListNode{Val: 5}}} + headA := &ListNode{Val: 4, Next: &ListNode{Val: 1, Next: intersectNode}} + headB := &ListNode{Val: 5, Next: &ListNode{Val: 6, Next: &ListNode{Val: 1, Next: intersectNode}}} + assert.Equal(t, intersectNode, getIntersectionNode(headA, headB)) +} From fda2f24162440c5d3c9cb822a3b6ca429a775d87 Mon Sep 17 00:00:00 2001 From: Austin Gebauer Date: Wed, 10 Mar 2021 09:58:53 -0800 Subject: [PATCH 02/14] plus_one_66: solved --- plus_one_66/README.md | 40 ++++++++++++++++++++++++ plus_one_66/solution.go | 22 +++++++++++++ plus_one_66/solution_test.go | 60 ++++++++++++++++++++++++++++++++++++ 3 files changed, 122 insertions(+) create mode 100644 plus_one_66/README.md create mode 100644 plus_one_66/solution.go create mode 100644 plus_one_66/solution_test.go diff --git a/plus_one_66/README.md b/plus_one_66/README.md new file mode 100644 index 0000000..9b067e4 --- /dev/null +++ b/plus_one_66/README.md @@ -0,0 +1,40 @@ +# 66. Plus One + +https://leetcode.com/problems/plus-one/ + +## Difficulty: + +Easy + +## Description + +Given a non-empty array of decimal digits representing a non-negative integer, increment one to the integer. + +The digits are stored such that the most significant digit is at the head of the list, and each +element in the array contains a single digit. + +You may assume the integer does not contain any leading zero, except the number 0 itself. + +Example 1: +``` +Input: digits = [1,2,3] +Output: [1,2,4] +Explanation: The array represents the integer 123. +``` + +Example 2: +``` +Input: digits = [4,3,2,1] +Output: [4,3,2,2] +Explanation: The array represents the integer 4321. +``` + +Example 3: +``` +Input: digits = [0] +Output: [1] +``` + +Constraints: +- 1 <= digits.length <= 100 +- 0 <= digits[i] <= 9 diff --git a/plus_one_66/solution.go b/plus_one_66/solution.go new file mode 100644 index 0000000..1be5bb8 --- /dev/null +++ b/plus_one_66/solution.go @@ -0,0 +1,22 @@ +package plus_one_66 + +func plusOne(digits []int) []int { + carry := 1 + for i := len(digits) - 1; i >= 0; i-- { + incr := digits[i] + carry + + if incr == 10 { + digits[i] = 0 + carry = 1 + } else { + digits[i] = incr + carry = 0 + } + } + + if carry == 1 { + return append([]int{1}, digits...) + } + + return digits +} diff --git a/plus_one_66/solution_test.go b/plus_one_66/solution_test.go new file mode 100644 index 0000000..3b70410 --- /dev/null +++ b/plus_one_66/solution_test.go @@ -0,0 +1,60 @@ +package plus_one_66 + +import ( + "reflect" + "testing" +) + +func Test_plusOne(t *testing.T) { + type args struct { + digits []int + } + tests := []struct { + name string + args args + want []int + }{ + { + name: "plus one", + args: args{ + digits: []int{1, 2, 3}, + }, + want: []int{1, 2, 4}, + }, + { + name: "plus one", + args: args{ + digits: []int{4, 3, 2, 1}, + }, + want: []int{4, 3, 2, 2}, + }, + { + name: "plus one", + args: args{ + digits: []int{0}, + }, + want: []int{1}, + }, + { + name: "plus one", + args: args{ + digits: []int{9, 9, 9}, + }, + want: []int{1, 0, 0, 0}, + }, + { + name: "plus one", + args: args{ + digits: []int{9}, + }, + want: []int{1, 0}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := plusOne(tt.args.digits); !reflect.DeepEqual(got, tt.want) { + t.Errorf("plusOne() = %v, want %v", got, tt.want) + } + }) + } +} From ab45e53e4a90ce1890f7ba3924c03fa01369a190 Mon Sep 17 00:00:00 2001 From: Austin Gebauer Date: Fri, 24 Nov 2023 12:46:00 -0800 Subject: [PATCH 03/14] merge_sorted_array_88: additional solution --- go.sum | 2 +- merge_sorted_array_88/solution.go | 21 ++++++++++++++++++++- merge_sorted_array_88/solution_test.go | 5 +++-- 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/go.sum b/go.sum index f520132..331fa69 100644 --- a/go.sum +++ b/go.sum @@ -1,4 +1,3 @@ -github.com/austingebauer/leetcode v0.0.0-20200305172347-4c676793876f h1:A/S3S1hRavbbUCRkWer4VGKpMhavNVroN1on5YFUH2I= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -6,6 +5,7 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/merge_sorted_array_88/solution.go b/merge_sorted_array_88/solution.go index 03aa1cd..3a21d7a 100644 --- a/merge_sorted_array_88/solution.go +++ b/merge_sorted_array_88/solution.go @@ -1,5 +1,24 @@ package merge_sorted_array_88 +// O(m+n) solution +func merge(nums1 []int, m int, nums2 []int, n int) { + if n == 0 { + return + } + + n1, n2, p := m-1, n-1, m+n-1 + for n2 > -1 { + if n1 < 0 || nums2[n2] >= nums1[n1] { + nums1[p] = nums2[n2] + n2-- + } else { + nums1[p] = nums1[n1] + n1-- + } + p-- + } +} + // Note: solution from rotate_string_796 interview that stumped me for a bit. // Wanted to solve without shifting and was tricky. func merge2(nums1 []int, m int, nums2 []int, n int) { @@ -34,7 +53,7 @@ func merge2(nums1 []int, m int, nums2 []int, n int) { } // Note: original solution with array shifting -func merge(nums1 []int, m int, nums2 []int, n int) { +func merge0(nums1 []int, m int, nums2 []int, n int) { slot := 0 // for each in nums2, insert into nums1 diff --git a/merge_sorted_array_88/solution_test.go b/merge_sorted_array_88/solution_test.go index ef40589..bb3ffe3 100644 --- a/merge_sorted_array_88/solution_test.go +++ b/merge_sorted_array_88/solution_test.go @@ -1,8 +1,9 @@ package merge_sorted_array_88 import ( - "github.com/stretchr/testify/assert" "testing" + + "github.com/stretchr/testify/assert" ) func Test_merge(t *testing.T) { @@ -68,7 +69,7 @@ func Test_merge(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - // merge2(tt.args.nums1, tt.args.m, tt.args.nums2, tt.args.n) + //merge0(tt.args.nums1, tt.args.m, tt.args.nums2, tt.args.n) merge(tt.args.nums1, tt.args.m, tt.args.nums2, tt.args.n) assert.Equal(t, tt.want, tt.args.nums1) }) From 8ceb9f454e912bb7b340d7b07ee4eebdd8dae1db Mon Sep 17 00:00:00 2001 From: Austin Gebauer Date: Sat, 25 Nov 2023 19:15:43 -0800 Subject: [PATCH 04/14] remove_duplicates_from_sorted_array_26: solved --- .../README.md | 3 ++ .../solution.go | 22 +++++++++++ .../solution_test.go | 37 +++++++++++++++++++ 3 files changed, 62 insertions(+) create mode 100644 remove_duplicates_from_sorted_array_26/README.md create mode 100644 remove_duplicates_from_sorted_array_26/solution.go create mode 100644 remove_duplicates_from_sorted_array_26/solution_test.go diff --git a/remove_duplicates_from_sorted_array_26/README.md b/remove_duplicates_from_sorted_array_26/README.md new file mode 100644 index 0000000..fd02fe4 --- /dev/null +++ b/remove_duplicates_from_sorted_array_26/README.md @@ -0,0 +1,3 @@ +# 26. Remove Duplicates from Sorted Array + +https://leetcode.com/problems/remove-duplicates-from-sorted-array/description/ diff --git a/remove_duplicates_from_sorted_array_26/solution.go b/remove_duplicates_from_sorted_array_26/solution.go new file mode 100644 index 0000000..5c81293 --- /dev/null +++ b/remove_duplicates_from_sorted_array_26/solution.go @@ -0,0 +1,22 @@ +package remove_duplicates_from_sorted_array_26 + +func removeDuplicates(nums []int) int { + i, j, u := 0, 0, 1 + for j < len(nums)-1 { + j = i + for j < len(nums)-1 && nums[i] == nums[j] { + j++ + } + if nums[i] != nums[j] { + u++ + } + + for k := j - 1; k > i; k-- { + nums[k] = nums[j] + } + + i++ + } + + return u +} diff --git a/remove_duplicates_from_sorted_array_26/solution_test.go b/remove_duplicates_from_sorted_array_26/solution_test.go new file mode 100644 index 0000000..617bd27 --- /dev/null +++ b/remove_duplicates_from_sorted_array_26/solution_test.go @@ -0,0 +1,37 @@ +package remove_duplicates_from_sorted_array_26 + +import "testing" + +func Test_removeDuplicates(t *testing.T) { + type args struct { + nums []int + } + tests := []struct { + name string + args args + want int + }{ + { + name: "remove duplicates", + args: args{nums: []int{1, 1, 2}}, + want: 2, + }, + { + name: "remove duplicates", + args: args{nums: []int{1, 1}}, + want: 1, + }, + { + name: "remove duplicates", + args: args{nums: []int{0, 0, 1, 1, 1, 2, 2, 3, 3, 4}}, + want: 5, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := removeDuplicates(tt.args.nums); got != tt.want { + t.Errorf("removeDuplicates() = %v, want %v", got, tt.want) + } + }) + } +} From c754ccbab40e8ec470dbe58dc5eda0ab89d8ef81 Mon Sep 17 00:00:00 2001 From: Austin Gebauer Date: Tue, 6 Aug 2024 07:32:13 -0700 Subject: [PATCH 05/14] merge_strings_alternately_1768: solved --- merge_strings_alternately_1768/README.md | 3 ++ merge_strings_alternately_1768/solution.go | 27 ++++++++++ .../solution_test.go | 49 +++++++++++++++++++ 3 files changed, 79 insertions(+) create mode 100644 merge_strings_alternately_1768/README.md create mode 100644 merge_strings_alternately_1768/solution.go create mode 100644 merge_strings_alternately_1768/solution_test.go diff --git a/merge_strings_alternately_1768/README.md b/merge_strings_alternately_1768/README.md new file mode 100644 index 0000000..b146768 --- /dev/null +++ b/merge_strings_alternately_1768/README.md @@ -0,0 +1,3 @@ +# 1768. Merge Strings Alternately + +https://leetcode.com/problems/merge-strings-alternately diff --git a/merge_strings_alternately_1768/solution.go b/merge_strings_alternately_1768/solution.go new file mode 100644 index 0000000..3b33942 --- /dev/null +++ b/merge_strings_alternately_1768/solution.go @@ -0,0 +1,27 @@ +package add_two_numbers_2 + +func mergeAlternately(word1 string, word2 string) string { + var ( + res string + i, j, k int + ) + + for i+j < len(word1)+len(word2) { + if i < len(word1) && k%2 == 0 { + res += string(word1[i]) + i++ + if j < len(word2) { + k++ + } + } + if j < len(word2) && k%2 == 1 { + res += string(word2[j]) + j++ + if i < len(word1) { + k++ + } + } + } + + return res +} diff --git a/merge_strings_alternately_1768/solution_test.go b/merge_strings_alternately_1768/solution_test.go new file mode 100644 index 0000000..3cb7dc3 --- /dev/null +++ b/merge_strings_alternately_1768/solution_test.go @@ -0,0 +1,49 @@ +package add_two_numbers_2 + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func Test_mergeAlternately(t *testing.T) { + type args struct { + word1 string + word2 string + } + tests := []struct { + name string + args args + want string + }{ + { + name: "same length", + args: args{ + word1: "abc", + word2: "pqr", + }, + want: "apbqcr", + }, + { + name: "different length 1", + args: args{ + word1: "ab", + word2: "pqrs", + }, + want: "apbqrs", + }, + { + name: "different length 2", + args: args{ + word1: "abcd", + word2: "pq", + }, + want: "apbqcd", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equalf(t, tt.want, mergeAlternately(tt.args.word1, tt.args.word2), "mergeAlternately(%v, %v)", tt.args.word1, tt.args.word2) + }) + } +} From 527b11868f6af34175d036dfc7faf9ef5abca5b5 Mon Sep 17 00:00:00 2001 From: Austin Gebauer Date: Tue, 6 Aug 2024 08:08:14 -0700 Subject: [PATCH 06/14] move_zeroes_283: solved 2 --- move_zeroes_283/solution.go | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/move_zeroes_283/solution.go b/move_zeroes_283/solution.go index a6693ba..df49546 100644 --- a/move_zeroes_283/solution.go +++ b/move_zeroes_283/solution.go @@ -1,9 +1,9 @@ package move_zeroes_283 -// Note: tricky problem! // Ex: [1,0,0,3,12] -// i -// p +// +// i +// p func moveZeroes(nums []int) { placement := 0 for i := 0; i < len(nums); i++ { @@ -15,3 +15,17 @@ func moveZeroes(nums []int) { } } } + +func moveZeroes2(nums []int) { + i, j := 0, 1 + for j < len(nums) { + if nums[i] != 0 { + i++ + } + if nums[i] == 0 && nums[j] != 0 { + nums[i], nums[j] = nums[j], nums[i] + i++ + } + j++ + } +} From 4c8dc1bafca8ec91cd4e58d0ae1032ab2072b95f Mon Sep 17 00:00:00 2001 From: Austin Gebauer Date: Wed, 7 Aug 2024 08:14:56 -0700 Subject: [PATCH 07/14] maximum_average_subarray_i_643: solved --- maximum_average_subarray_i_643/README.md | 3 ++ maximum_average_subarray_i_643/solution.go | 24 +++++++++++ .../solution_test.go | 41 +++++++++++++++++++ merge_strings_alternately_1768/solution.go | 2 +- .../solution_test.go | 2 +- move_zeroes_283/solution_test.go | 3 +- 6 files changed, 72 insertions(+), 3 deletions(-) create mode 100644 maximum_average_subarray_i_643/README.md create mode 100644 maximum_average_subarray_i_643/solution.go create mode 100644 maximum_average_subarray_i_643/solution_test.go diff --git a/maximum_average_subarray_i_643/README.md b/maximum_average_subarray_i_643/README.md new file mode 100644 index 0000000..3f0b3d8 --- /dev/null +++ b/maximum_average_subarray_i_643/README.md @@ -0,0 +1,3 @@ +# 643. Maximum Average Subarray I + +https://leetcode.com/problems/maximum-average-subarray-i/description/ diff --git a/maximum_average_subarray_i_643/solution.go b/maximum_average_subarray_i_643/solution.go new file mode 100644 index 0000000..0141fa8 --- /dev/null +++ b/maximum_average_subarray_i_643/solution.go @@ -0,0 +1,24 @@ +package maximum_average_subarray_i_643 + +import "math" + +func findMaxAverage(nums []int, k int) float64 { + start := 0 + end := k - 1 + sum := 0.0 + + for i := start; i <= end; i++ { + sum += float64(nums[i]) + } + + maxAvg := sum / float64(k) + for end < len(nums)-1 { + sum -= float64(nums[start]) + sum += float64(nums[end+1]) + maxAvg = math.Max(maxAvg, sum/float64(k)) + start++ + end++ + } + + return maxAvg +} diff --git a/maximum_average_subarray_i_643/solution_test.go b/maximum_average_subarray_i_643/solution_test.go new file mode 100644 index 0000000..26b9643 --- /dev/null +++ b/maximum_average_subarray_i_643/solution_test.go @@ -0,0 +1,41 @@ +package maximum_average_subarray_i_643 + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func Test_findMaxAverage(t *testing.T) { + type args struct { + nums []int + k int + } + tests := []struct { + name string + args args + want float64 + }{ + { + name: "many numbers", + args: args{ + nums: []int{1, 12, -5, -6, 50, 3}, + k: 4, + }, + want: 12.75000, + }, + { + name: "single number", + args: args{ + nums: []int{5}, + k: 1, + }, + want: 5.00000, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equal(t, tt.want, findMaxAverage(tt.args.nums, tt.args.k)) + }) + } +} diff --git a/merge_strings_alternately_1768/solution.go b/merge_strings_alternately_1768/solution.go index 3b33942..8a53947 100644 --- a/merge_strings_alternately_1768/solution.go +++ b/merge_strings_alternately_1768/solution.go @@ -1,4 +1,4 @@ -package add_two_numbers_2 +package merge_strings_alternately_1768 func mergeAlternately(word1 string, word2 string) string { var ( diff --git a/merge_strings_alternately_1768/solution_test.go b/merge_strings_alternately_1768/solution_test.go index 3cb7dc3..76688c3 100644 --- a/merge_strings_alternately_1768/solution_test.go +++ b/merge_strings_alternately_1768/solution_test.go @@ -1,4 +1,4 @@ -package add_two_numbers_2 +package merge_strings_alternately_1768 import ( "testing" diff --git a/move_zeroes_283/solution_test.go b/move_zeroes_283/solution_test.go index bb61e9d..18f72ac 100644 --- a/move_zeroes_283/solution_test.go +++ b/move_zeroes_283/solution_test.go @@ -1,8 +1,9 @@ package move_zeroes_283 import ( - "github.com/stretchr/testify/assert" "testing" + + "github.com/stretchr/testify/assert" ) func Test_moveZeroes(t *testing.T) { From 69e1354a37c117f5839e6ccaa515ea703a32139d Mon Sep 17 00:00:00 2001 From: Austin Gebauer Date: Thu, 8 Aug 2024 08:23:55 -0700 Subject: [PATCH 08/14] find_the_highest_altitude_1732: solved --- find_the_highest_altitude_1732/README.md | 3 ++ find_the_highest_altitude_1732/solution.go | 26 +++++++++++++++ .../solution_test.go | 32 +++++++++++++++++++ template/README.md | 3 ++ template/solution.go | 1 + template/solution_test.go | 1 + 6 files changed, 66 insertions(+) create mode 100644 find_the_highest_altitude_1732/README.md create mode 100644 find_the_highest_altitude_1732/solution.go create mode 100644 find_the_highest_altitude_1732/solution_test.go create mode 100644 template/README.md create mode 100644 template/solution.go create mode 100644 template/solution_test.go diff --git a/find_the_highest_altitude_1732/README.md b/find_the_highest_altitude_1732/README.md new file mode 100644 index 0000000..e752828 --- /dev/null +++ b/find_the_highest_altitude_1732/README.md @@ -0,0 +1,3 @@ +# Number. Title + +TODO: link to problem \ No newline at end of file diff --git a/find_the_highest_altitude_1732/solution.go b/find_the_highest_altitude_1732/solution.go new file mode 100644 index 0000000..90ed24b --- /dev/null +++ b/find_the_highest_altitude_1732/solution.go @@ -0,0 +1,26 @@ +package template + +import "math" + +// -4 -3 -2 -1 4 3 2 +// +// ^ +// +// -4 -7 -9 -10 -6 -3 -1 +func largestAltitude(gain []int) int { + prefixSums := make([]int, len(gain)) + for i, g := range gain { + toAdd := 0 + if i > 0 { + toAdd = prefixSums[i-1] + } + prefixSums[i] = toAdd + g + } + + // catch is that zero starting point could be the highest altitude + max := 0 + for _, s := range prefixSums { + max = int(math.Max(float64(max), float64(s))) + } + return max +} diff --git a/find_the_highest_altitude_1732/solution_test.go b/find_the_highest_altitude_1732/solution_test.go new file mode 100644 index 0000000..b753c24 --- /dev/null +++ b/find_the_highest_altitude_1732/solution_test.go @@ -0,0 +1,32 @@ +package template + +import "testing" + +func Test_largestAltitude(t *testing.T) { + type args struct { + gain []int + } + tests := []struct { + name string + args args + want int + }{ + { + name: "1", + args: args{gain: []int{-5, 1, 5, 0, -7}}, + want: 1, + }, + { + name: "2", + args: args{gain: []int{-4, -3, -2, -1, 4, 3, 2}}, + want: 0, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := largestAltitude(tt.args.gain); got != tt.want { + t.Errorf("largestAltitude() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/template/README.md b/template/README.md new file mode 100644 index 0000000..c96daf2 --- /dev/null +++ b/template/README.md @@ -0,0 +1,3 @@ +# Number. Title + +https://leetcode.com/problems/find-the-highest-altitude/description/ \ No newline at end of file diff --git a/template/solution.go b/template/solution.go new file mode 100644 index 0000000..38cdfe4 --- /dev/null +++ b/template/solution.go @@ -0,0 +1 @@ +package template diff --git a/template/solution_test.go b/template/solution_test.go new file mode 100644 index 0000000..38cdfe4 --- /dev/null +++ b/template/solution_test.go @@ -0,0 +1 @@ +package template From 8d441d4227287d7ab9be418373fdef09c65067fe Mon Sep 17 00:00:00 2001 From: Austin Gebauer Date: Thu, 8 Aug 2024 08:24:15 -0700 Subject: [PATCH 09/14] find_the_highest_altitude_1732: fix package name --- find_the_highest_altitude_1732/solution.go | 2 +- find_the_highest_altitude_1732/solution_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/find_the_highest_altitude_1732/solution.go b/find_the_highest_altitude_1732/solution.go index 90ed24b..3922906 100644 --- a/find_the_highest_altitude_1732/solution.go +++ b/find_the_highest_altitude_1732/solution.go @@ -1,4 +1,4 @@ -package template +package find_the_highest_altitude_1732 import "math" diff --git a/find_the_highest_altitude_1732/solution_test.go b/find_the_highest_altitude_1732/solution_test.go index b753c24..14341a1 100644 --- a/find_the_highest_altitude_1732/solution_test.go +++ b/find_the_highest_altitude_1732/solution_test.go @@ -1,4 +1,4 @@ -package template +package find_the_highest_altitude_1732 import "testing" From da0ff4c2e559f366da4f9f53f65cd9937223e44e Mon Sep 17 00:00:00 2001 From: Austin Gebauer Date: Thu, 8 Aug 2024 08:24:45 -0700 Subject: [PATCH 10/14] find_the_highest_altitude_1732: rename var --- find_the_highest_altitude_1732/solution.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/find_the_highest_altitude_1732/solution.go b/find_the_highest_altitude_1732/solution.go index 3922906..a95cea0 100644 --- a/find_the_highest_altitude_1732/solution.go +++ b/find_the_highest_altitude_1732/solution.go @@ -18,9 +18,9 @@ func largestAltitude(gain []int) int { } // catch is that zero starting point could be the highest altitude - max := 0 + highest := 0 for _, s := range prefixSums { - max = int(math.Max(float64(max), float64(s))) + highest = int(math.Max(float64(highest), float64(s))) } - return max + return highest } From 9c87db3b0e3c7042f731e6891498ded60c2bf1a7 Mon Sep 17 00:00:00 2001 From: Austin Gebauer Date: Sun, 11 Aug 2024 16:27:04 -0700 Subject: [PATCH 11/14] find_the_difference_of_two_arrays_2215: solved --- .../README.md | 3 ++ .../solution.go | 29 +++++++++++++ .../solution_test.go | 43 +++++++++++++++++++ go.mod | 8 +++- 4 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 find_the_difference_of_two_arrays_2215/README.md create mode 100644 find_the_difference_of_two_arrays_2215/solution.go create mode 100644 find_the_difference_of_two_arrays_2215/solution_test.go diff --git a/find_the_difference_of_two_arrays_2215/README.md b/find_the_difference_of_two_arrays_2215/README.md new file mode 100644 index 0000000..a5742c6 --- /dev/null +++ b/find_the_difference_of_two_arrays_2215/README.md @@ -0,0 +1,3 @@ +# 2215. Find the Difference of Two Arrays + +https://leetcode.com/problems/find-the-difference-of-two-arrays/description/ \ No newline at end of file diff --git a/find_the_difference_of_two_arrays_2215/solution.go b/find_the_difference_of_two_arrays_2215/solution.go new file mode 100644 index 0000000..51830a9 --- /dev/null +++ b/find_the_difference_of_two_arrays_2215/solution.go @@ -0,0 +1,29 @@ +package find_the_difference_of_two_arrays_2215 + +func findDifference(nums1 []int, nums2 []int) [][]int { + set1 := sliceToSet(nums1) + set2 := sliceToSet(nums2) + diff := make([][]int, 2) + diff[0] = setDifference(set1, set2) + diff[1] = setDifference(set2, set1) + return diff +} + +func setDifference(s1, s2 map[int]struct{}) []int { + var res []int + for k := range s1 { + if _, ok := s2[k]; !ok { + res = append(res, k) + } + } + + return res +} + +func sliceToSet(a []int) map[int]struct{} { + s := make(map[int]struct{}) + for _, v := range a { + s[v] = struct{}{} + } + return s +} diff --git a/find_the_difference_of_two_arrays_2215/solution_test.go b/find_the_difference_of_two_arrays_2215/solution_test.go new file mode 100644 index 0000000..e61b459 --- /dev/null +++ b/find_the_difference_of_two_arrays_2215/solution_test.go @@ -0,0 +1,43 @@ +package find_the_difference_of_two_arrays_2215 + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func Test_findDifference(t *testing.T) { + type args struct { + nums1 []int + nums2 []int + } + tests := []struct { + name string + args args + want [][]int + }{ + { + name: "1", + args: args{ + nums1: []int{1, 2, 3}, + nums2: []int{2, 4, 6}, + }, + want: [][]int{{1, 3}, {4, 6}}, + }, + { + name: "2", + args: args{ + nums1: []int{1, 2, 3, 3}, + nums2: []int{1, 1, 2, 2}, + }, + want: [][]int{{3}, nil}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := findDifference(tt.args.nums1, tt.args.nums2) + assert.ElementsMatch(t, tt.want[0], got[0]) + assert.ElementsMatch(t, tt.want[1], got[1]) + }) + } +} diff --git a/go.mod b/go.mod index 24d7208..ffa2aa9 100644 --- a/go.mod +++ b/go.mod @@ -1,5 +1,11 @@ module github.com/austingebauer/go-leetcode -go 1.14 +go 1.22.6 require github.com/stretchr/testify v1.5.1 + +require ( + github.com/davecgh/go-spew v1.1.0 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + gopkg.in/yaml.v2 v2.2.2 // indirect +) From 1c1328ff20a4810529edfabbf2a5567300ec9bd0 Mon Sep 17 00:00:00 2001 From: Austin Gebauer Date: Tue, 7 Jan 2025 20:59:10 -0800 Subject: [PATCH 12/14] flatten_nested_list_iterator_341: solved --- flatten_nested_list_iterator_341/solution.go | 133 ++++++++++++++++++ .../solution_test.go | 66 +++++++++ 2 files changed, 199 insertions(+) create mode 100644 flatten_nested_list_iterator_341/solution.go create mode 100644 flatten_nested_list_iterator_341/solution_test.go diff --git a/flatten_nested_list_iterator_341/solution.go b/flatten_nested_list_iterator_341/solution.go new file mode 100644 index 0000000..466a445 --- /dev/null +++ b/flatten_nested_list_iterator_341/solution.go @@ -0,0 +1,133 @@ +package flatten_nested_list_iterator_341 + +/** + * // This is the interface that allows for creating nested lists. + * // You should not implement it, or speculate about its implementation + * type NestedInteger struct { + * } + * + * // Return true if this NestedInteger holds a single integer, rather than a nested list. + * func (this NestedInteger) IsInteger() bool {} + * + * // Return the single integer that this NestedInteger holds, if it holds a single integer + * // The result is undefined if this NestedInteger holds a nested list + * // So before calling this method, you should have a check + * func (this NestedInteger) GetInteger() int {} + * + * // Set this NestedInteger to hold a single integer. + * func (n *NestedInteger) SetInteger(value int) {} + * + * // Set this NestedInteger to hold a nested list and adds a nested integer to it. + * func (this *NestedInteger) Add(elem NestedInteger) {} + * + * // Return the nested list that this NestedInteger holds, if it holds a nested list + * // The list length is zero if this NestedInteger holds a single integer + * // You can access NestedInteger's List element directly if you want to modify it + * func (this NestedInteger) GetList() []*NestedInteger {} + */ + +type NestedInteger struct { + value any + isInt bool +} + +func NewNestedInteger(value any) *NestedInteger { + var isInt bool + if _, ok := value.(int); ok { + isInt = true + } + return &NestedInteger{ + value: value, + isInt: isInt, + } +} + +func (this NestedInteger) IsInteger() bool { + return this.isInt +} +func (this NestedInteger) GetInteger() int { + v := this.value.(int) + return v +} +func (this NestedInteger) GetList() []*NestedInteger { + v := this.value.([]*NestedInteger) + return v +} + +type ListIndex struct { + Idx int + List []*NestedInteger +} + +type Stack struct { + items []*ListIndex +} + +func (s *Stack) Push(v *ListIndex) { + s.items = append(s.items, v) +} + +func (s *Stack) Pop() *ListIndex { + if len(s.items) <= 0 { + return nil + } + + val := s.items[len(s.items)-1] + s.items = s.items[:len(s.items)-1] + return val +} + +func (s *Stack) Peek() *ListIndex { + if len(s.items) <= 0 { + return nil + } + + return s.items[len(s.items)-1] +} + +func (s *Stack) IsEmpty() bool { + return len(s.items) == 0 +} + +type NestedIterator struct { + stack *Stack +} + +func Constructor(nestedList []*NestedInteger) *NestedIterator { + stack := new(Stack) + stack.Push(&ListIndex{ + Idx: 0, + List: nestedList, + }) + + return &NestedIterator{ + stack: stack, + } +} + +func (this *NestedIterator) Next() int { + current := this.stack.Peek() + for !current.List[current.Idx].IsInteger() { + next := &ListIndex{ + Idx: 0, + List: current.List[current.Idx].GetList(), + } + this.stack.Push(next) + + current.Idx++ + current = next + } + + value := current.List[current.Idx].GetInteger() + current.Idx++ + + if current.Idx == len(current.List) { + this.stack.Pop() + } + + return value +} + +func (this *NestedIterator) HasNext() bool { + return !this.stack.IsEmpty() && this.stack.Peek().Idx != len(this.stack.Peek().List) +} diff --git a/flatten_nested_list_iterator_341/solution_test.go b/flatten_nested_list_iterator_341/solution_test.go new file mode 100644 index 0000000..f7d6463 --- /dev/null +++ b/flatten_nested_list_iterator_341/solution_test.go @@ -0,0 +1,66 @@ +package flatten_nested_list_iterator_341 + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestIterator(t *testing.T) { + type args struct { + list []*NestedInteger + } + + tests := []struct { + name string + args args + want []int + }{ + { + name: "1", + args: args{ + // [[1,1],2,[1,1]] + list: []*NestedInteger{ + NewNestedInteger([]*NestedInteger{ + NewNestedInteger(1), + NewNestedInteger(1), + }), + NewNestedInteger(2), + NewNestedInteger([]*NestedInteger{ + NewNestedInteger(1), + NewNestedInteger(1), + }), + }, + }, + want: []int{1, 1, 2, 1, 1}, + }, + { + name: "1", + args: args{ + // [1,[4,[6]]] + list: []*NestedInteger{ + NewNestedInteger(1), + NewNestedInteger([]*NestedInteger{ + NewNestedInteger(4), + NewNestedInteger([]*NestedInteger{ + NewNestedInteger(6), + }), + }), + }, + }, + want: []int{1, 4, 6}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + var got []int + + itr := Constructor(tt.args.list) + for itr.HasNext() { + got = append(got, itr.Next()) + } + assert.Equal(t, tt.want, got) + }) + } +} From 341ad88727fa664ee81c5ee396158fc202b19459 Mon Sep 17 00:00:00 2001 From: Austin Gebauer Date: Tue, 7 Jan 2025 21:02:23 -0800 Subject: [PATCH 13/14] design_sql_2408: solved --- design_sql_2408/README.md | 3 ++ design_sql_2408/solution.go | 85 +++++++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+) create mode 100644 design_sql_2408/README.md create mode 100644 design_sql_2408/solution.go diff --git a/design_sql_2408/README.md b/design_sql_2408/README.md new file mode 100644 index 0000000..5951c0d --- /dev/null +++ b/design_sql_2408/README.md @@ -0,0 +1,3 @@ +# 2408. Design SQL + +https://leetcode.com/problems/design-sql/description/ \ No newline at end of file diff --git a/design_sql_2408/solution.go b/design_sql_2408/solution.go new file mode 100644 index 0000000..c13a4f4 --- /dev/null +++ b/design_sql_2408/solution.go @@ -0,0 +1,85 @@ +package design_sql_2408 + +import ( + "fmt" + "strings" +) + +type table struct { + idInc int + colCount int + rows map[int][]string +} + +type SQL struct { + tables map[string]*table +} + +func Constructor(names []string, columns []int) SQL { + sql := SQL{ + tables: make(map[string]*table), + } + for i, name := range names { + colCount := columns[i] + sql.tables[name] = &table{ + idInc: 0, + colCount: colCount, + rows: make(map[int][]string), + } + } + + return sql +} + +func (q *SQL) Ins(name string, row []string) bool { + table, ok := q.tables[name] + if !ok || len(row) != table.colCount { + return false + } + + table.idInc++ + table.rows[table.idInc] = row + return true +} + +func (q *SQL) Rmv(name string, rowId int) { + table, ok := q.tables[name] + if !ok { + return + } + + // deletes are idempotent, no need to check if it exists or not + delete(table.rows, rowId) +} + +func (q *SQL) Sel(name string, rowId int, columnId int) string { + table, ok := q.tables[name] + if !ok { + return "" + } + + row, ok := table.rows[rowId] + if !ok { + return "" + } + + if columnId < 1 || columnId > len(row) { + return "" + } + + return row[columnId-1] +} + +func (q *SQL) Exp(name string) []string { + table, ok := q.tables[name] + if !ok { + return []string{} + } + + rows := make([]string, 0, len(table.rows)) + for id, row := range table.rows { + rows = append(rows, fmt.Sprintf("%d,%s", id, strings.Join(row, ","))) + } + + return rows +} From 0c6e04f8ece193d3b2c78c308bcfa39f4cf61ac2 Mon Sep 17 00:00:00 2001 From: Austin Gebauer Date: Tue, 7 Jan 2025 21:14:45 -0800 Subject: [PATCH 14/14] time_based_key_value_store_981: solved --- time_based_key_value_store_981/README.md | 3 + time_based_key_value_store_981/solution.go | 61 +++++++++++++++++++ .../solution_test.go | 18 ++++++ 3 files changed, 82 insertions(+) create mode 100644 time_based_key_value_store_981/README.md create mode 100644 time_based_key_value_store_981/solution.go create mode 100644 time_based_key_value_store_981/solution_test.go diff --git a/time_based_key_value_store_981/README.md b/time_based_key_value_store_981/README.md new file mode 100644 index 0000000..b54e661 --- /dev/null +++ b/time_based_key_value_store_981/README.md @@ -0,0 +1,3 @@ +# 981. Time Based Key-Value Store + +https://leetcode.com/problems/time-based-key-value-store/description/ \ No newline at end of file diff --git a/time_based_key_value_store_981/solution.go b/time_based_key_value_store_981/solution.go new file mode 100644 index 0000000..7c99dc8 --- /dev/null +++ b/time_based_key_value_store_981/solution.go @@ -0,0 +1,61 @@ +package time_based_key_value_store_981 + +import "sort" + +type entry struct { + value string + timestamp int +} + +type TimeMap struct { + m map[string][]*entry +} + +func Constructor() TimeMap { + return TimeMap{ + m: make(map[string][]*entry), + } +} + +func (m *TimeMap) Set(key string, value string, timestamp int) { + entries, ok := m.m[key] + if !ok { + entries = make([]*entry, 0) + } + + // perform a binary search for the sorted insertion point (timestamp asc) + index := sort.Search(len(entries), func(i int) bool { + return entries[i].timestamp > timestamp + }) + + // insert the new entry at the sorted insertion point + newEntry := &entry{value: value, timestamp: timestamp} + if index == len(entries) { + entries = append(entries, newEntry) + } else { + // perform a copy-shift insert + entries = append(entries, nil) // make space + copy(entries[index+1:], entries[index:]) + entries[index] = newEntry + } + + m.m[key] = entries +} + +func (m *TimeMap) Get(key string, timestamp int) string { + entries, ok := m.m[key] + if !ok { + return "" + } + + // Find the first entry where the timestamp is greater. This means + // the one right behind it is our entry to return. + index := sort.Search(len(entries), func(i int) bool { + return entries[i].timestamp > timestamp + }) + if index == 0 { + return "" + } + + return entries[index-1].value +} diff --git a/time_based_key_value_store_981/solution_test.go b/time_based_key_value_store_981/solution_test.go new file mode 100644 index 0000000..1b141fe --- /dev/null +++ b/time_based_key_value_store_981/solution_test.go @@ -0,0 +1,18 @@ +package time_based_key_value_store_981 + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestKV(t *testing.T) { + kv := Constructor() + kv.Set("foo", "bar", 1) + kv.Set("foo", "baz", 4) + assert.Equal(t, "", kv.Get("foo", 0)) + assert.Equal(t, "bar", kv.Get("foo", 3)) + assert.Equal(t, "bar", kv.Get("foo", 2)) + assert.Equal(t, "baz", kv.Get("foo", 4)) + assert.Equal(t, "baz", kv.Get("foo", 6)) +}