├── README.md ├── arrays ├── addtoarrayformofinteger │ ├── addtoarrayformofinteger.go │ └── addtoarrayformofinteger_test.go ├── availablecapturesforrook │ ├── availablecapturesforrook.go │ └── availablecapturesforrook_test.go ├── besttimetobuyandsellstock │ ├── besttimetobuyandsellstock.go │ └── besttimetobuyandsellstock_test.go ├── duplicatezeros │ ├── duplicatezeros.go │ └── duplicatezeros_test.go ├── findmaxconsecutiveones │ ├── findMaxConsecutiveOnes.go │ └── findMaxConsecutiveOnes_test.go ├── largestnumberatleasttwiceofothers │ ├── largestnumberatleasttwiceofothers.go │ └── largestnumberatleasttwiceofothers_test.go ├── maximumproductsubarray │ ├── maximumproductsubarray.go │ └── maximumproductsubarray_test.go ├── maximumsubarray │ ├── maximumsubarray.go │ └── maximumsubarray_test.go ├── numberofequivalentdominopairs │ ├── numberofequivalentdominopairs.go │ └── numberofequivalentdominopairs_test.go ├── pairsofsongswithtotaldurationsdivisibleby60 │ ├── pairsofsongswithtotaldurationsdivisibleby60.go │ └── pairsofsongswithtotaldurationsdivisibleby60_test.go ├── partitionarrayintothreepartswithequalsum │ ├── partitionarrayintothreepartswithequalsum.go │ └── partitionarrayintothreepartswithequalsum_test.go ├── plusone │ ├── plusone.go │ └── plusone_test.go ├── relativesortarray │ ├── relativesortarray.go │ └── relativesortarray_test.go ├── searchinsertposition │ ├── searchinsertposition.go │ └── searchinsertposition_test.go ├── sumevenafterqueries │ ├── sumevenafterqueries.go │ └── sumevenafterqueries_test.go ├── thirdmaximumnumber │ ├── thirdmaximumnumber.go │ ├── thirdmaximumnumber_test.go │ └── xpto.html ├── twosum │ ├── two_sum.go │ └── two_sum_test.go └── twosum_sortedarray │ ├── twosum_sortedarray.go │ └── twosum_sortedarray_test.go ├── linkedlist ├── addtwonumbers │ ├── addtwonumbers.go │ └── addtwonumbers_test.go ├── designlinkedlist │ ├── designlinkedlist.go │ └── designlinkedlist_test.go ├── listnode │ └── listnode.go ├── removeduplicatesfromsortedlist │ ├── removeduplicatesfromsortedlist.go │ └── removeduplicatesfromsortedlist_test.go └── reverselinkedlist │ ├── reverselinkedlist.go │ └── reverselinkedlist_test.go ├── strings ├── buddystrings │ ├── buddystrings.go │ └── buddystrings_test.go ├── detectcapitaluse │ ├── detectcapitaluse.go │ └── detectcapitaluse_test.go ├── findcommonchars │ ├── findcommonchars.go │ └── findcommonchars_test.go ├── jewelsandstones │ ├── jewelsandstones.go │ └── jewelsandstones_test.go ├── lengthoflongestsubstring │ ├── lengthoflongestsubstring.go │ └── lengthoflongestsubstring_test.go ├── maxoccurringchar │ ├── maxoccurringchar.go │ └── maxoccurringchar_test.go ├── numberofsegmentsinastring │ ├── numberofsegmentsinastring.go │ └── numberofsegmentsinastring_test.go ├── reverseonlyletters │ ├── reverse_only_letters.go │ └── reverseonlyletters_test.go ├── reversevowels │ ├── reversevowels.go │ └── reversevowels_test.go ├── reversewordsinastringiii │ ├── reversewordsinastringiii.go │ └── reversewordsinastringiii_test.go ├── singlerowkeyboard │ ├── singlerowkeyboard.go │ └── singlerowkeyboard_test.go └── validparentheses │ ├── validparentheses.go │ └── validparentheses_test.go └── testutils └── testutils.go /README.md: -------------------------------------------------------------------------------- 1 | # Solutions to leetcode problems using Golang 2 | 3 | I am a Golang beginner, please read my code and tell me what I can do better ;) 4 | 5 | My leetcode profile: https://leetcode.com/wennder/ 6 | 7 | ## Table content 8 | * [Arrays](/arrays) 9 | * [LinkedLists](/linkedlist) 10 | * [Strings](/strings) 11 | -------------------------------------------------------------------------------- /arrays/addtoarrayformofinteger/addtoarrayformofinteger.go: -------------------------------------------------------------------------------- 1 | package addtoarrayformofinteger 2 | 3 | //AddToArrayForm executes in 4 | //Time: 5 | //Memory: 6 | func AddToArrayForm(A []int, K int) []int { 7 | result, j, i := [10001]int{}, 0, len(A)-1 8 | 9 | carry := 0 10 | for i >= 0 || K > 0 || carry == 1 { 11 | sum := carry 12 | if i >= 0 { 13 | sum += A[i] 14 | i-- 15 | } 16 | 17 | if K != 0 { 18 | sum += K % 10 19 | K /= 10 20 | } 21 | 22 | result[j] = sum % 10 23 | carry = sum / 10 24 | j++ 25 | } 26 | 27 | for l, h := 0, j-1; l < h; l, h = l+1, h-1 { 28 | result[l], result[h] = result[h], result[l] 29 | } 30 | 31 | return result[:j] 32 | } 33 | 34 | //989. Add to Array-Form of Integer 35 | //https://leetcode.com/problems/add-to-array-form-of-integer/ 36 | -------------------------------------------------------------------------------- /arrays/addtoarrayformofinteger/addtoarrayformofinteger_test.go: -------------------------------------------------------------------------------- 1 | package addtoarrayformofinteger 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/wenndersantos/leetcode-in-go/testutils" 7 | ) 8 | 9 | func TestAddToArrayForm(t *testing.T) { 10 | testCases := []struct { 11 | arr []int 12 | k int 13 | want []int 14 | }{ 15 | { 16 | arr: []int{1, 2, 0, 0}, 17 | k: 34, 18 | want: []int{1, 2, 3, 4}, 19 | }, 20 | { 21 | arr: []int{2, 7, 4}, 22 | k: 181, 23 | want: []int{4, 5, 5}, 24 | }, 25 | { 26 | arr: []int{2, 1, 5}, 27 | k: 806, 28 | want: []int{1, 0, 2, 1}, 29 | }, 30 | { 31 | arr: []int{9, 9, 9, 9, 9, 9, 9, 9, 9, 9}, 32 | k: 1, 33 | want: []int{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 34 | }, 35 | { 36 | arr: []int{0}, 37 | k: 0, 38 | want: []int{0}, 39 | }, 40 | { 41 | arr: []int{1, 2, 6, 3, 0, 7, 1, 7, 1, 9, 7, 5, 6, 6, 4, 4, 0, 0, 6, 3}, 42 | k: 516, 43 | want: []int{1, 2, 6, 3, 0, 7, 1, 7, 1, 9, 7, 5, 6, 6, 4, 4, 0, 5, 7, 9}, 44 | }, 45 | { 46 | arr: []int{3, 8, 0, 3, 0, 2, 7, 0, 7, 6, 4, 9, 9, 1, 7, 6, 6, 1, 6, 4}, 47 | k: 670, 48 | want: []int{3, 8, 0, 3, 0, 2, 7, 0, 7, 6, 4, 9, 9, 1, 7, 6, 6, 8, 3, 4}, 49 | }, 50 | } 51 | 52 | for _, tc := range testCases { 53 | got := AddToArrayForm(tc.arr, tc.k) 54 | 55 | if !testutils.IntSliceAreEqual(got, tc.want) { 56 | t.Errorf("\narr %v, k %d\ngot: %v\nwant: %v", tc.arr, tc.k, got, tc.want) 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /arrays/availablecapturesforrook/availablecapturesforrook.go: -------------------------------------------------------------------------------- 1 | package availablecapturesforrook 2 | 3 | func rPosition(board [][]byte) []int { 4 | for i := 0; i < len(board); i++ { 5 | for j := 0; j < len(board[0]); j++ { 6 | if board[i][j] == 'R' { 7 | return []int{i, j} 8 | } 9 | } 10 | } 11 | 12 | return []int{} 13 | } 14 | 15 | func captures(board [][]byte, rposition []int, x int, y int) int { 16 | i, j := rposition[0], rposition[1] 17 | 18 | for i < len(board) && i >= 0 && j < len(board[0]) && j >= 0 { 19 | if board[i][j] == 'p' { 20 | return 1 21 | } 22 | 23 | if board[i][j] == 'B' { 24 | return 0 25 | } 26 | 27 | i, j = i+x, j+y 28 | } 29 | 30 | return 0 31 | } 32 | 33 | //NumRookCaptures executes in 34 | //Time: O(n*m) worst case will look into the entire matrix to find 'R' 35 | //Memory: O(1) 36 | func NumRookCaptures(board [][]byte) int { 37 | rposition := rPosition(board) 38 | 39 | left := captures(board, rposition, 0, -1) 40 | right := captures(board, rposition, 0, +1) 41 | top := captures(board, rposition, -1, 0) 42 | bottom := captures(board, rposition, +1, 0) 43 | 44 | return left + right + top + bottom 45 | } 46 | 47 | //999. Available Captures for Rook 48 | //https://leetcode.com/problems/available-captures-for-rook/ 49 | -------------------------------------------------------------------------------- /arrays/availablecapturesforrook/availablecapturesforrook_test.go: -------------------------------------------------------------------------------- 1 | package availablecapturesforrook 2 | 3 | import "testing" 4 | 5 | func TestNumRookCaptures(t *testing.T) { 6 | testCases := []struct { 7 | input [][]byte 8 | want int 9 | }{ 10 | { 11 | input: [][]byte{{'.', '.', '.', '.', '.', '.', '.', '.'}, {'.', '.', '.', 'p', '.', '.', '.', '.'}, {'.', '.', '.', 'R', '.', '.', '.', 'p'}, {'.', '.', '.', '.', '.', '.', '.', '.'}, {'.', '.', '.', '.', '.', '.', '.', '.'}, {'.', '.', '.', 'p', '.', '.', '.', '.'}, {'.', '.', '.', '.', '.', '.', '.', '.'}, {'.', '.', '.', '.', '.', '.', '.', '.'}}, 12 | want: 3, 13 | }, 14 | { 15 | input: [][]byte{{'.', '.', '.', '.', '.', '.', '.', '.'}, {'.', 'p', 'p', 'p', 'p', 'p', '.', '.'}, {'.', 'p', 'p', 'B', 'p', 'p', '.', '.'}, {'.', 'p', 'B', 'R', 'B', 'p', '.', '.'}, {'.', 'p', 'p', 'B', 'p', 'p', '.', '.'}, {'.', 'p', 'p', 'p', 'p', 'p', '.', '.'}, {'.', '.', '.', '.', '.', '.', '.', '.'}, {'.', '.', '.', '.', '.', '.', '.', '.'}}, 16 | want: 0, 17 | }, 18 | { 19 | input: [][]byte{{'.', '.', '.', '.', '.', '.', '.', '.'}, {'.', '.', '.', 'p', '.', '.', '.', '.'}, {'.', '.', '.', 'p', '.', '.', '.', '.'}, {'p', 'p', '.', 'R', '.', 'p', 'B', '.'}, {'.', '.', '.', '.', '.', '.', '.', '.'}, {'.', '.', '.', 'B', '.', '.', '.', '.'}, {'.', '.', '.', 'p', '.', '.', '.', '.'}, {'.', '.', '.', '.', '.', '.', '.', '.'}}, 20 | want: 3, 21 | }, 22 | } 23 | 24 | for _, tc := range testCases { 25 | got := NumRookCaptures(tc.input) 26 | 27 | if got != tc.want { 28 | t.Errorf("\ninput: %v\ngot: %d, want: %d", tc.input, got, tc.want) 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /arrays/besttimetobuyandsellstock/besttimetobuyandsellstock.go: -------------------------------------------------------------------------------- 1 | package besttimetobuyandsellstock 2 | 3 | //MaxProfit executes in 4 | //Time: O(n) where n is the length of prices 5 | //Memory: O(1) 6 | func MaxProfit(prices []int) int { 7 | result, buyAt := 0, 0 8 | 9 | for i := 1; i < len(prices); i++ { 10 | if prices[i] < prices[buyAt] { 11 | buyAt = i 12 | } else if (prices[i] - prices[buyAt]) > result { 13 | result = prices[i] - prices[buyAt] 14 | } 15 | } 16 | return result 17 | } 18 | 19 | //121. Best Time to Buy and Sell Stock 20 | //https://leetcode.com/problems/best-time-to-buy-and-sell-stock/ 21 | -------------------------------------------------------------------------------- /arrays/besttimetobuyandsellstock/besttimetobuyandsellstock_test.go: -------------------------------------------------------------------------------- 1 | package besttimetobuyandsellstock 2 | 3 | import "testing" 4 | 5 | func TestMaxProfit(t *testing.T) { 6 | testCases := []struct { 7 | input []int 8 | want int 9 | }{ 10 | { 11 | input: []int{}, 12 | want: 0, 13 | }, 14 | { 15 | input: []int{1}, 16 | want: 0, 17 | }, 18 | { 19 | input: []int{7, 1, 5, 3, 6, 4}, 20 | want: 5, 21 | }, 22 | } 23 | 24 | for _, tc := range testCases { 25 | got := MaxProfit(tc.input) 26 | 27 | if got != tc.want { 28 | t.Errorf("input: %v - got: %d, want: %d", tc.input, got, tc.want) 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /arrays/duplicatezeros/duplicatezeros.go: -------------------------------------------------------------------------------- 1 | package duplicatezeros 2 | 3 | //DuplicateZeros executes in 4 | //Time: O(n^2) - the entire array is 0 in worst case 5 | //Memory: O(1) done in place 6 | func DuplicateZeros(arr []int) []int { 7 | lastIndex := len(arr) - 1 8 | 9 | for i := lastIndex; i >= 0; i-- { 10 | if arr[i] == 0 && i != lastIndex { 11 | aux := arr[i+1] 12 | arr[i+1] = 0 13 | j := i + 2 14 | 15 | for j <= lastIndex { 16 | aux, arr[j] = arr[j], aux 17 | j++ 18 | } 19 | } 20 | } 21 | 22 | return arr 23 | } 24 | 25 | //1089. Duplicate Zeros 26 | //https://leetcode.com/problems/duplicate-zeros/ 27 | -------------------------------------------------------------------------------- /arrays/duplicatezeros/duplicatezeros_test.go: -------------------------------------------------------------------------------- 1 | package duplicatezeros 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/wenndersantos/leetcode-in-go/testutils" 7 | ) 8 | 9 | func TestDuplicateZeros(t *testing.T) { 10 | testCases := []struct { 11 | input []int 12 | want []int 13 | }{ 14 | { 15 | input: []int{1, 0, 2, 3, 0, 4, 5, 0}, 16 | want: []int{1, 0, 0, 2, 3, 0, 0, 4}, 17 | }, 18 | { 19 | input: []int{1, 2, 3}, 20 | want: []int{1, 2, 3}, 21 | }, 22 | } 23 | 24 | for _, tc := range testCases { 25 | got := DuplicateZeros(tc.input) 26 | 27 | if !testutils.IntSliceAreEqual(got, tc.want) { 28 | t.Errorf("input: %v - got: %v, want: %v", tc.input, got, tc.want) 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /arrays/findmaxconsecutiveones/findMaxConsecutiveOnes.go: -------------------------------------------------------------------------------- 1 | package findmaxconsecutiveones 2 | 3 | //FindMaxConsecutiveOnes executes in 4 | //Time: O(n) 5 | //Memory: O(1) 6 | func FindMaxConsecutiveOnes(nums []int) int { 7 | result, count := 0, 0 8 | 9 | for _, val := range nums { 10 | count *= val 11 | count += val 12 | 13 | if count > result { 14 | result = count 15 | } 16 | } 17 | 18 | return result 19 | } 20 | 21 | //485. Max Consecutive Ones 22 | //https://leetcode.com/problems/max-consecutive-ones/ 23 | -------------------------------------------------------------------------------- /arrays/findmaxconsecutiveones/findMaxConsecutiveOnes_test.go: -------------------------------------------------------------------------------- 1 | package findmaxconsecutiveones 2 | 3 | import "testing" 4 | 5 | func TestFindMaxConsecutiveOnes(t *testing.T) { 6 | testCases := []struct { 7 | input []int 8 | want int 9 | }{ 10 | { 11 | input: []int{1, 1, 0, 1, 1, 1}, 12 | want: 3, 13 | }, 14 | { 15 | input: []int{0, 0, 0, 0}, 16 | want: 0, 17 | }, 18 | { 19 | input: []int{1, 1, 1, 1}, 20 | want: 4, 21 | }, 22 | } 23 | 24 | for _, tc := range testCases { 25 | got := FindMaxConsecutiveOnes(tc.input) 26 | 27 | if got != tc.want { 28 | t.Errorf("input: %v - got %d, want %d", tc.input, got, tc.want) 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /arrays/largestnumberatleasttwiceofothers/largestnumberatleasttwiceofothers.go: -------------------------------------------------------------------------------- 1 | package largestnumberatleasttwiceofothers 2 | 3 | //DominantIndex executes in 4 | //Time: O(n) where n is the length of nums 5 | //Memory: O(1) 6 | func DominantIndex(nums []int) int { 7 | if len(nums) == 1 { 8 | return 0 9 | } 10 | 11 | i, biggest, secondBiggest := 1, 0, 0 12 | 13 | for i < len(nums) { 14 | if nums[biggest] < nums[i] { 15 | secondBiggest = biggest 16 | biggest = i 17 | } else if secondBiggest == biggest || nums[secondBiggest] < nums[i] { 18 | secondBiggest = i 19 | } 20 | i++ 21 | } 22 | 23 | if nums[biggest] >= nums[secondBiggest]*2 { 24 | return biggest 25 | } 26 | 27 | return -1 28 | } 29 | 30 | //747. Largest Number At Least Twice of Others 31 | //https://leetcode.com/problems/largest-number-at-least-twice-of-others/ 32 | -------------------------------------------------------------------------------- /arrays/largestnumberatleasttwiceofothers/largestnumberatleasttwiceofothers_test.go: -------------------------------------------------------------------------------- 1 | package largestnumberatleasttwiceofothers 2 | 3 | import "testing" 4 | 5 | func TestDominantIndex(t *testing.T) { 6 | testCases := []struct { 7 | input []int 8 | want int 9 | }{ 10 | { 11 | input: []int{1}, 12 | want: 0, 13 | }, 14 | { 15 | input: []int{1, 0}, 16 | want: 0, 17 | }, 18 | { 19 | input: []int{0, 0, 0, 1}, 20 | want: 3, 21 | }, 22 | { 23 | input: []int{3, 6, 1, 0}, 24 | want: 1, 25 | }, 26 | { 27 | input: []int{1, 2, 3, 4}, 28 | want: -1, 29 | }, 30 | } 31 | 32 | for _, tc := range testCases { 33 | got := DominantIndex(tc.input) 34 | 35 | if got != tc.want { 36 | t.Errorf("input: %v - got: %d, want: %d", tc.input, got, tc.want) 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /arrays/maximumproductsubarray/maximumproductsubarray.go: -------------------------------------------------------------------------------- 1 | package maximumproductsubarray 2 | 3 | //MaxProduct executes in 4 | //Time: O(n) - where n is the length of nums 5 | //Memory: O(1) 6 | func MaxProduct(nums []int) int { 7 | if len(nums) == 0 { 8 | return 0 9 | } 10 | 11 | if len(nums) == 1 { 12 | return nums[0] 13 | } 14 | 15 | result, currMin, currMax := nums[0], nums[0], nums[0] 16 | for i := 1; i < len(nums); i++ { 17 | if nums[i] < 0 { 18 | currMax, currMin = currMin, currMax 19 | } 20 | 21 | if nums[i] > currMax*nums[i] { 22 | currMax = nums[i] 23 | } else { 24 | currMax *= nums[i] 25 | } 26 | 27 | if nums[i] < currMin*nums[i] { 28 | currMin = nums[i] 29 | } else { 30 | currMin *= nums[i] 31 | } 32 | 33 | if result < currMax { 34 | result = currMax 35 | } 36 | 37 | } 38 | return result 39 | } 40 | 41 | //152. Maximum Product Subarray 42 | //https://leetcode.com/problems/maximum-product-subarray/ 43 | -------------------------------------------------------------------------------- /arrays/maximumproductsubarray/maximumproductsubarray_test.go: -------------------------------------------------------------------------------- 1 | package maximumproductsubarray 2 | 3 | import "testing" 4 | 5 | func TestMaxProduct(t *testing.T) { 6 | testCases := []struct { 7 | input []int 8 | want int 9 | }{ 10 | { 11 | input: []int{}, 12 | want: 0, 13 | }, 14 | { 15 | input: []int{-2}, 16 | want: -2, 17 | }, 18 | { 19 | input: []int{0, 2}, 20 | want: 2, 21 | }, 22 | { 23 | input: []int{2, 3, -2, 4}, 24 | want: 6, 25 | }, 26 | { 27 | input: []int{-2, 0, -1}, 28 | want: 0, 29 | }, 30 | { 31 | input: []int{-2, 3, -4}, 32 | want: 24, 33 | }, 34 | } 35 | 36 | for _, tc := range testCases { 37 | got := MaxProduct(tc.input) 38 | 39 | if got != tc.want { 40 | t.Errorf("input: %v - got: %d, want: %d", tc.input, got, tc.want) 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /arrays/maximumsubarray/maximumsubarray.go: -------------------------------------------------------------------------------- 1 | package maximumsubarray 2 | 3 | //MaxSubArray executes in 4 | //Time: O(n) - where n is the length of nums 5 | //Memory: O(1) 6 | func MaxSubArray(nums []int) int { 7 | if len(nums) == 0 { 8 | return 0 9 | } 10 | 11 | result, currMax := nums[0], nums[0] 12 | for i := 1; i < len(nums); i++ { 13 | if nums[i] > currMax+nums[i] { 14 | currMax = nums[i] 15 | } else { 16 | currMax += nums[i] 17 | } 18 | 19 | if currMax > result { 20 | result = currMax 21 | } 22 | } 23 | 24 | return result 25 | } 26 | 27 | //53. Maximum Subarray 28 | //https://leetcode.com/problems/maximum-subarray/ 29 | -------------------------------------------------------------------------------- /arrays/maximumsubarray/maximumsubarray_test.go: -------------------------------------------------------------------------------- 1 | package maximumsubarray 2 | 3 | import "testing" 4 | 5 | func TestMaximumSubarray(t *testing.T) { 6 | testCases := []struct { 7 | input []int 8 | want int 9 | }{ 10 | { 11 | input: []int{}, 12 | want: 0, 13 | }, 14 | { 15 | input: []int{0}, 16 | want: 0, 17 | }, 18 | { 19 | input: []int{-2, 1, -3, 4, -1, 2, 1, -5, 4}, 20 | want: 6, 21 | }, 22 | } 23 | 24 | for _, tc := range testCases { 25 | got := MaxSubArray(tc.input) 26 | 27 | if got != tc.want { 28 | t.Errorf("input: %v - got: %d, want: %d", tc.input, got, tc.want) 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /arrays/numberofequivalentdominopairs/numberofequivalentdominopairs.go: -------------------------------------------------------------------------------- 1 | package numberofequivalentdominopairs 2 | 3 | //NumEquivDominoPairs executes in 4 | //Time: O(n) wheren n is the length of dominoes 5 | //Memory: O(1) using a fixed size []int 6 | func NumEquivDominoPairs(dominoes [][]int) int { 7 | if dominoes == nil || len(dominoes) == 0 { 8 | return 0 9 | } 10 | 11 | result := 0 12 | occurrences := [100]int{} 13 | 14 | for _, dominoe := range dominoes { 15 | key, rotatedKey := dominoe[0]*10+dominoe[1], dominoe[1]*10+dominoe[0] 16 | 17 | if key != rotatedKey { 18 | result += occurrences[rotatedKey] 19 | } 20 | 21 | result += occurrences[key] 22 | occurrences[key]++ 23 | } 24 | 25 | return result 26 | } 27 | 28 | //1128. Number of Equivalent Domino Pairs 29 | //https://leetcode.com/problems/number-of-equivalent-domino-pairs/ 30 | -------------------------------------------------------------------------------- /arrays/numberofequivalentdominopairs/numberofequivalentdominopairs_test.go: -------------------------------------------------------------------------------- 1 | package numberofequivalentdominopairs 2 | 3 | import "testing" 4 | 5 | func TestNumEquivDominoPairs(t *testing.T) { 6 | testCases := []struct { 7 | input [][]int 8 | want int 9 | }{ 10 | { 11 | input: [][]int{}, 12 | want: 0, 13 | }, 14 | { 15 | input: nil, 16 | want: 0, 17 | }, 18 | { 19 | input: [][]int{{1, 2}, {2, 1}, {3, 4}, {5, 6}}, 20 | want: 1, 21 | }, 22 | { 23 | input: [][]int{{9, 8}, {2, 1}, {8, 9}, {1, 2}}, 24 | want: 2, 25 | }, 26 | { 27 | input: [][]int{{1, 2}, {2, 1}, {8, 9}, {1, 2}}, 28 | want: 3, 29 | }, 30 | { 31 | input: [][]int{{1, 2}, {1, 2}, {1, 1}, {1, 2}, {2, 2}}, 32 | want: 3, 33 | }, 34 | { 35 | input: [][]int{{1, 1}, {2, 2}, {1, 1}, {1, 2}, {1, 2}, {1, 1}}, 36 | want: 4, 37 | }, 38 | { 39 | input: [][]int{{2, 1}, {1, 2}, {1, 2}, {1, 2}, {2, 1}, {1, 1}, {1, 2}, {2, 2}}, 40 | want: 15, 41 | }, 42 | } 43 | 44 | for _, tc := range testCases { 45 | got := NumEquivDominoPairs(tc.input) 46 | 47 | if got != tc.want { 48 | t.Errorf("input %v - got: %d, want %d", tc.input, got, tc.want) 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /arrays/pairsofsongswithtotaldurationsdivisibleby60/pairsofsongswithtotaldurationsdivisibleby60.go: -------------------------------------------------------------------------------- 1 | package pairsofsongswithtotaldurationsdivisibleby60 2 | 3 | //NumPairsDivisibleBy60 executes in 4 | //Time: O(n) where n is the length of time 5 | //Memory: O(1) fixed size [60]int 6 | func NumPairsDivisibleBy60(time []int) int { 7 | result, target := 0, 60 8 | memory := [60]int{} 9 | 10 | for _, songDuration := range time { 11 | d := songDuration % target 12 | if d == 0 { 13 | result += memory[d] 14 | } else { 15 | result += memory[target-d] 16 | } 17 | memory[d]++ 18 | } 19 | 20 | return result 21 | } 22 | 23 | //1010. Pairs of Songs With Total Durations Divisible by 60 24 | //https://leetcode.com/problems/pairs-of-songs-with-total-durations-divisible-by-60/ 25 | -------------------------------------------------------------------------------- /arrays/pairsofsongswithtotaldurationsdivisibleby60/pairsofsongswithtotaldurationsdivisibleby60_test.go: -------------------------------------------------------------------------------- 1 | package pairsofsongswithtotaldurationsdivisibleby60 2 | 3 | import "testing" 4 | 5 | func TestNumPairsDivisibleBy60(t *testing.T) { 6 | testCases := []struct { 7 | input []int 8 | want int 9 | }{ 10 | { 11 | input: []int{}, 12 | want: 0, 13 | }, 14 | { 15 | input: []int{30, 20, 150, 100, 40}, 16 | want: 3, 17 | }, 18 | { 19 | input: []int{60, 60, 60}, 20 | want: 3, 21 | }, 22 | } 23 | 24 | for _, tc := range testCases { 25 | got := NumPairsDivisibleBy60(tc.input) 26 | 27 | if got != tc.want { 28 | t.Errorf("input: %v - got: %d, want: %d", tc.input, got, tc.want) 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /arrays/partitionarrayintothreepartswithequalsum/partitionarrayintothreepartswithequalsum.go: -------------------------------------------------------------------------------- 1 | package partitionarrayintothreepartswithequalsum 2 | 3 | //CanThreePartsEqualSum executes in 4 | //Time: O(n) where n is de length of A 5 | //Memory: O(1) 6 | func CanThreePartsEqualSum(A []int) bool { 7 | if len(A) < 3 { 8 | return false 9 | } 10 | 11 | totalSum := 0 12 | for _, val := range A { 13 | totalSum += val 14 | } 15 | 16 | if totalSum%3 != 0 { 17 | return false 18 | } 19 | 20 | partitionSum := totalSum / 3 21 | numberOfPartitions := 3 22 | auxSum := 0 23 | for _, val := range A { 24 | auxSum += val 25 | if auxSum == partitionSum { 26 | auxSum = 0 27 | numberOfPartitions-- 28 | } 29 | 30 | //just neest to find 2 partitions 31 | if numberOfPartitions == 1 { 32 | return true 33 | } 34 | } 35 | 36 | return false 37 | } 38 | 39 | //1013. Partition Array Into Three Parts With Equal Sum 40 | //https://leetcode.com/problems/partition-array-into-three-parts-with-equal-sum/ 41 | -------------------------------------------------------------------------------- /arrays/partitionarrayintothreepartswithequalsum/partitionarrayintothreepartswithequalsum_test.go: -------------------------------------------------------------------------------- 1 | package partitionarrayintothreepartswithequalsum 2 | 3 | import "testing" 4 | 5 | func TestCanThreePartsEqualSum(t *testing.T) { 6 | testCases := []struct { 7 | input []int 8 | want bool 9 | }{ 10 | { 11 | input: []int{1, 1}, 12 | want: false, 13 | }, 14 | { 15 | input: []int{1, 1, 3}, 16 | want: false, 17 | }, 18 | { 19 | input: []int{0, 2, 1, -6, 6, -7, 9, 1, 2, 0, 1}, 20 | want: true, 21 | }, 22 | { 23 | input: []int{0, 2, 1, -6, 6, 7, 9, -1, 2, 0, 1}, 24 | want: false, 25 | }, 26 | { 27 | input: []int{3, 3, 6, 5, -2, 2, 5, 1, -9, 4}, 28 | want: true, 29 | }, 30 | } 31 | 32 | for _, tc := range testCases { 33 | got := CanThreePartsEqualSum(tc.input) 34 | 35 | if got != tc.want { 36 | t.Errorf("input: %v - got: %t, want: %t", tc.input, got, tc.want) 37 | } 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /arrays/plusone/plusone.go: -------------------------------------------------------------------------------- 1 | package plusone 2 | 3 | //PlusOne executes in 4 | //Time: O(n) - where n is the length of digits 5 | //Memory: O(1) 6 | func PlusOne(digits []int) []int { 7 | if len(digits) == 0 { 8 | return digits 9 | } 10 | 11 | for i := len(digits) - 1; i >= 0; i-- { 12 | if digits[i] != 9 { 13 | digits[i]++ 14 | return digits 15 | } 16 | digits[i] = 0 17 | } 18 | 19 | return append([]int{1}, digits...) 20 | } 21 | 22 | //66. Plus One 23 | //https://leetcode.com/problems/plus-one/ 24 | -------------------------------------------------------------------------------- /arrays/plusone/plusone_test.go: -------------------------------------------------------------------------------- 1 | package plusone 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/wenndersantos/leetcode-in-go/testutils" 7 | ) 8 | 9 | func TestPlusOne(t *testing.T) { 10 | testCases := []struct { 11 | input []int 12 | want []int 13 | }{ 14 | { 15 | input: []int{}, 16 | want: []int{}, 17 | }, 18 | { 19 | input: []int{1}, 20 | want: []int{2}, 21 | }, 22 | { 23 | input: []int{1, 2, 3}, 24 | want: []int{1, 2, 4}, 25 | }, 26 | { 27 | input: []int{4, 3, 2, 1}, 28 | want: []int{4, 3, 2, 2}, 29 | }, 30 | { 31 | input: []int{1, 2, 9}, 32 | want: []int{1, 3, 0}, 33 | }, 34 | { 35 | input: []int{9, 9, 9}, 36 | want: []int{1, 0, 0, 0}, 37 | }, 38 | } 39 | 40 | for _, tc := range testCases { 41 | got := PlusOne(tc.input) 42 | 43 | if !testutils.IntSliceAreEqual(got, tc.want) { 44 | t.Errorf("input: %v - got: %v, want: %v", tc.input, got, tc.want) 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /arrays/relativesortarray/relativesortarray.go: -------------------------------------------------------------------------------- 1 | package relativesortarray 2 | 3 | import ( 4 | "sort" 5 | ) 6 | 7 | //RelativeSortArray executes in 8 | //Time: O(n^2) 9 | //Memory: O(1) - done in place 10 | func RelativeSortArray(arr1 []int, arr2 []int) []int { 11 | if len(arr1) == 0 || len(arr2) == 0 { 12 | return arr1 13 | } 14 | 15 | i, j := 0, 0 16 | 17 | for _, val := range arr2 { 18 | for i < len(arr1) && arr1[i] == val { 19 | i++ 20 | } 21 | 22 | j = i + 1 23 | 24 | for j < len(arr1) { 25 | if arr1[j] == val { 26 | arr1[j], arr1[i] = arr1[i], arr1[j] 27 | i++ 28 | } 29 | j++ 30 | } 31 | } 32 | 33 | if i < len(arr1) { 34 | sort.Sort(sort.IntSlice(arr1[i:])) 35 | } 36 | 37 | return arr1 38 | } 39 | 40 | //RelativeSortArray2 executes in 41 | //Time: O(n*Logn) - sort 42 | //Memory: O(n) - where n is the length of arr1 43 | func RelativeSortArray2(arr1 []int, arr2 []int) []int { 44 | if len(arr1) == 0 || len(arr2) == 0 { 45 | return arr1 46 | } 47 | 48 | memory := map[int]int{} 49 | for _, val := range arr1 { 50 | if _, ok := memory[val]; ok { 51 | memory[val]++ 52 | } else { 53 | memory[val] = 1 54 | } 55 | } 56 | 57 | i := 0 58 | result := [1000]int{} 59 | for _, val := range arr2 { 60 | if ocurrences, ok := memory[val]; ok { 61 | for ocurrences > 0 { 62 | result[i] = val 63 | i++ 64 | ocurrences-- 65 | } 66 | 67 | delete(memory, val) 68 | } 69 | } 70 | 71 | j := i 72 | for key, ocurrences := range memory { 73 | for ocurrences > 0 { 74 | result[i] = key 75 | i++ 76 | ocurrences-- 77 | } 78 | 79 | delete(memory, key) 80 | } 81 | 82 | if j < len(arr1) { 83 | sort.Sort(sort.IntSlice(result[j:i])) 84 | } 85 | 86 | return result[:i] 87 | } 88 | 89 | //1122. Relative Sort Array 90 | //https://leetcode.com/problems/relative-sort-array/ 91 | -------------------------------------------------------------------------------- /arrays/relativesortarray/relativesortarray_test.go: -------------------------------------------------------------------------------- 1 | package relativesortarray 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/wenndersantos/leetcode-in-go/testutils" 7 | ) 8 | 9 | func TestRelativeSortArray(t *testing.T) { 10 | testCases := []struct { 11 | arr1 []int 12 | arr2 []int 13 | want []int 14 | }{ 15 | { 16 | arr1: []int{2, 3, 1, 3, 2, 4, 6, 7, 9, 2, 19}, 17 | arr2: []int{2, 1, 4, 3, 9, 6}, 18 | want: []int{2, 2, 2, 1, 4, 3, 3, 9, 6, 7, 19}, 19 | }, 20 | { 21 | arr1: []int{943, 790, 427, 722, 860, 550, 225, 846, 715, 320}, 22 | arr2: []int{943, 715, 427, 790, 860, 722, 225, 320, 846, 550}, 23 | want: []int{943, 715, 427, 790, 860, 722, 225, 320, 846, 550}, 24 | }, 25 | { 26 | arr1: []int{28, 6, 22, 8, 44, 17}, 27 | arr2: []int{22, 28, 8, 6}, 28 | want: []int{22, 28, 8, 6, 17, 44}, 29 | }, 30 | { 31 | arr1: []int{2, 21, 43, 38, 0, 42, 33, 7, 24, 13, 12, 27, 12, 24, 5, 23, 29, 48, 30, 31}, 32 | arr2: []int{2, 42, 38, 0, 43, 21}, 33 | want: []int{2, 42, 38, 0, 43, 21, 5, 7, 12, 12, 13, 23, 24, 24, 27, 29, 30, 31, 33, 48}, 34 | }, 35 | } 36 | 37 | for _, tc := range testCases { 38 | got := RelativeSortArray(tc.arr1, tc.arr2) 39 | 40 | if !testutils.IntSliceAreEqual(got, tc.want) { 41 | t.Errorf("\narr1: %v\narr2: %v\ngot: %v, want: %v", tc.arr1, tc.arr2, got, tc.want) 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /arrays/searchinsertposition/searchinsertposition.go: -------------------------------------------------------------------------------- 1 | package searchinsertposition 2 | 3 | //SearchInsert executes in 4 | //Time: O(log n) - binary search 5 | //Memory: O(1) 6 | func SearchInsert(nums []int, target int) int { 7 | l, h := 0, len(nums)-1 8 | 9 | for l <= h { 10 | mid := (l + h) / 2 11 | 12 | if nums[mid] == target { 13 | return mid 14 | } else if target > nums[mid] { 15 | l = mid + 1 16 | } else { 17 | h = mid - 1 18 | } 19 | } 20 | 21 | return l 22 | } 23 | 24 | //35. Search Insert Position 25 | //https://leetcode.com/problems/search-insert-position/submissions/ 26 | -------------------------------------------------------------------------------- /arrays/searchinsertposition/searchinsertposition_test.go: -------------------------------------------------------------------------------- 1 | package searchinsertposition 2 | 3 | import "testing" 4 | 5 | func TestSearchInsert(t *testing.T) { 6 | testCases := []struct { 7 | arr []int 8 | target int 9 | want int 10 | }{ 11 | { 12 | arr: []int{}, 13 | target: 1, 14 | want: 0, 15 | }, 16 | { 17 | arr: []int{1, 3, 5, 6}, 18 | target: 5, 19 | want: 2, 20 | }, 21 | { 22 | arr: []int{1, 3, 5, 6}, 23 | target: 2, 24 | want: 1, 25 | }, 26 | { 27 | arr: []int{1, 3, 5, 6}, 28 | target: 7, 29 | want: 4, 30 | }, 31 | { 32 | arr: []int{1, 3, 5, 6}, 33 | target: 0, 34 | want: 0, 35 | }, 36 | } 37 | 38 | for _, tc := range testCases { 39 | got := SearchInsert(tc.arr, tc.target) 40 | 41 | if got != tc.want { 42 | t.Errorf("arr: %v, target: %d - got: %d, want: %d", tc.arr, tc.target, got, tc.want) 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /arrays/sumevenafterqueries/sumevenafterqueries.go: -------------------------------------------------------------------------------- 1 | package sumevenafterqueries 2 | 3 | //SumEvenAfterQueries executes in 4 | //Time: 5 | //Memory: O(1) - fixed sized result array 6 | func SumEvenAfterQueries(A []int, queries [][]int) []int { 7 | sum := 0 8 | 9 | for _, val := range A { 10 | if val%2 == 0 { 11 | sum += val 12 | } 13 | } 14 | 15 | result := [10001]int{} 16 | 17 | for i, querie := range queries { 18 | idx, val := querie[1], querie[0] 19 | if A[idx]%2 == 0 { 20 | sum -= A[idx] 21 | } 22 | 23 | A[idx] += val 24 | 25 | if A[idx]%2 == 0 { 26 | sum += A[idx] 27 | } 28 | 29 | result[i] = sum 30 | } 31 | 32 | return result[:len(queries)] 33 | } 34 | 35 | //985. Sum of Even Numbers After Queries 36 | //https://leetcode.com/problems/sum-of-even-numbers-after-queries/ 37 | -------------------------------------------------------------------------------- /arrays/sumevenafterqueries/sumevenafterqueries_test.go: -------------------------------------------------------------------------------- 1 | package sumevenafterqueries 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/wenndersantos/leetcode-in-go/testutils" 7 | ) 8 | 9 | func TestSumEvenAfterQueries(t *testing.T) { 10 | testCases := []struct { 11 | arr []int 12 | queries [][]int 13 | want []int 14 | }{ 15 | { 16 | arr: []int{1, 2, 3, 4}, 17 | queries: [][]int{{1, 0}, {-3, 1}, {-4, 0}, {2, 3}}, 18 | want: []int{8, 6, 2, 4}, 19 | }, 20 | } 21 | 22 | for _, tc := range testCases { 23 | got := SumEvenAfterQueries(tc.arr, tc.queries) 24 | 25 | if !testutils.IntSliceAreEqual(got, tc.want) { 26 | t.Errorf("\narr: %v\nqueries: %v\ngot: %v\nwant: %v", tc.arr, tc.queries, got, tc.want) 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /arrays/thirdmaximumnumber/thirdmaximumnumber.go: -------------------------------------------------------------------------------- 1 | package thirdmaximumnumber 2 | 3 | import "math" 4 | 5 | //ThirdMax executes in 6 | //Time: O(n) where n is the length of nums 7 | //Memory: O(1) 8 | //This could also be done using fixed size heap in time O(n log n) 9 | func ThirdMax(nums []int) int { 10 | if len(nums) == 0 { 11 | return 0 12 | } 13 | 14 | first, second, third := math.MinInt32, math.MinInt32, math.MinInt32 15 | foundMinIntInArray, count := 0, 0 16 | 17 | for i := 0; i < len(nums); i++ { 18 | val := nums[i] 19 | if val == first || val == second || val == third { 20 | if val == math.MinInt32 { 21 | foundMinIntInArray = 1 22 | } 23 | continue 24 | } 25 | 26 | if val > first { 27 | third, second, first = second, first, val 28 | } else if val > second { 29 | third, second = second, val 30 | } else if val > third { 31 | third = val 32 | } 33 | 34 | count++ 35 | } 36 | 37 | if count+foundMinIntInArray > 2 { 38 | return third 39 | } 40 | return first //there is no third maximum, so return maximum value 41 | } 42 | 43 | //414. Third Maximum Number 44 | //https://leetcode.com/problems/third-maximum-number/ 45 | -------------------------------------------------------------------------------- /arrays/thirdmaximumnumber/thirdmaximumnumber_test.go: -------------------------------------------------------------------------------- 1 | package thirdmaximumnumber 2 | 3 | import "testing" 4 | 5 | func TestThirdMax(t *testing.T) { 6 | testCases := []struct { 7 | input []int 8 | want int 9 | }{ 10 | { 11 | input: []int{}, 12 | want: 0, 13 | }, 14 | { 15 | input: []int{1}, 16 | want: 1, 17 | }, 18 | { 19 | input: []int{1, 2}, 20 | want: 2, 21 | }, 22 | { 23 | input: []int{3, 2, 1}, 24 | want: 1, 25 | }, 26 | { 27 | input: []int{2, 2, 3, 1}, 28 | want: 1, 29 | }, 30 | { 31 | input: []int{1, 1, 2}, 32 | want: 2, 33 | }, 34 | { 35 | input: []int{1, 2, -2147483648}, 36 | want: -2147483648, 37 | }, 38 | } 39 | 40 | for _, tc := range testCases { 41 | got := ThirdMax(tc.input) 42 | 43 | if got != tc.want { 44 | t.Errorf("input: %v - got: %d, want: %d", tc.input, got, tc.want) 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /arrays/thirdmaximumnumber/xpto.html: -------------------------------------------------------------------------------- 1 |
  1. All About Birds 2 |
    1. Kinds of Birds 3 |
      1. The Finch 4 |
      2. 5 |
      3. The Swan 6 |
    2. 7 |
    3. Habitats 8 |
      1. Wetlands 9 |
-------------------------------------------------------------------------------- /arrays/twosum/two_sum.go: -------------------------------------------------------------------------------- 1 | package twosum 2 | 3 | //TwoSum executes in 4 | //time: O(n) where N is the length of nums 5 | //memory: O(n) which is the memory used by the hashmap 6 | func TwoSum(nums []int, target int) []int { 7 | memory := map[int]int{} 8 | 9 | for i, item := range nums { 10 | if val, ok := memory[item]; ok { 11 | return []int{val, i} 12 | } 13 | 14 | memory[target-item] = i 15 | } 16 | return []int{} 17 | } 18 | 19 | //1. Two Sum 20 | //https://leetcode.com/problems/two-sum/ 21 | -------------------------------------------------------------------------------- /arrays/twosum/two_sum_test.go: -------------------------------------------------------------------------------- 1 | package twosum 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/wenndersantos/leetcode-in-go/testutils" 7 | ) 8 | 9 | func TestTwoSum(t *testing.T) { 10 | cases := []struct { 11 | arr []int 12 | target int 13 | want []int 14 | }{ 15 | {[]int{1, 2, 3, 5, 6, 7}, 4, []int{0, 2}}, 16 | {[]int{1, 2, 3, 5, 6, 7}, 15, []int{}}, 17 | } 18 | 19 | for _, testcase := range cases { 20 | got := TwoSum(testcase.arr, testcase.target) 21 | 22 | if !testutils.IntSliceAreEqual(got, testcase.want) { 23 | t.Errorf("Sum was incorrect, got: %d, want: %d.", got, testcase.want) 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /arrays/twosum_sortedarray/twosum_sortedarray.go: -------------------------------------------------------------------------------- 1 | package twosumsortedarray 2 | 3 | //TwoSumSortedArray executes in 4 | //Time: O(n) where N is the length of numbers 5 | //Memory: O(1) - As the array is sorted, I am using 6 | //the strategy of two pointers (low and high). 7 | //This exercise on leetcode expects the result indexes in base 1 8 | //thats the why of []int{l + 1, h + 1} 9 | func TwoSumSortedArray(numbers []int, target int) []int { 10 | l, h := 0, len(numbers)-1 11 | 12 | for l < h { 13 | if (numbers[l] + numbers[h]) > target { 14 | h-- 15 | } else if (numbers[l] + numbers[h]) < target { 16 | l++ 17 | } else { 18 | return []int{l + 1, h + 1} 19 | } 20 | } 21 | return []int{} 22 | } 23 | 24 | //167. Two Sum II - Input array is sorted 25 | //https://leetcode.com/problems/two-sum-ii-input-array-is-sorted/ 26 | -------------------------------------------------------------------------------- /arrays/twosum_sortedarray/twosum_sortedarray_test.go: -------------------------------------------------------------------------------- 1 | package twosumsortedarray 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/wenndersantos/leetcode-in-go/testutils" 7 | ) 8 | 9 | func TestTwoSumSortedArray(t *testing.T) { 10 | cases := []struct { 11 | arr []int 12 | target int 13 | want []int 14 | }{ 15 | {[]int{1, 2, 3, 5, 6, 7}, 4, []int{1, 3}}, 16 | {[]int{1, 2, 3, 5, 6, 7, 20}, 15, []int{}}, 17 | } 18 | 19 | for _, testcase := range cases { 20 | got := TwoSumSortedArray(testcase.arr, testcase.target) 21 | 22 | if !testutils.IntSliceAreEqual(got, testcase.want) { 23 | t.Errorf("input: %d - got: %d, want: %d.", testcase.arr, got, testcase.want) 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /linkedlist/addtwonumbers/addtwonumbers.go: -------------------------------------------------------------------------------- 1 | package addtwonumbers 2 | 3 | //ListNode is a node of a linkedlist 4 | type ListNode struct { 5 | Val int 6 | Next *ListNode 7 | } 8 | 9 | //AddTwoNumbers Executes in 10 | //Time: O(n) where n is the length of the biggest list 11 | //Memory: O(n) where n is the length of result list 12 | func AddTwoNumbers(l1 *ListNode, l2 *ListNode) *ListNode { 13 | head := ListNode{} 14 | current := &head 15 | carry, sum := 0, 0 16 | 17 | for l1 != nil || l2 != nil || carry != 0 { 18 | sum = carry 19 | 20 | if l1 != nil { 21 | sum += l1.Val 22 | l1 = l1.Next 23 | } 24 | 25 | if l2 != nil { 26 | sum += l2.Val 27 | l2 = l2.Next 28 | } 29 | 30 | carry = sum / 10 31 | current.Next = &ListNode{Val: sum % 10} 32 | current = current.Next 33 | } 34 | 35 | return head.Next 36 | } 37 | 38 | //2. Add Two Numbers 39 | //https://leetcode.com/problems/add-two-numbers/ 40 | -------------------------------------------------------------------------------- /linkedlist/addtwonumbers/addtwonumbers_test.go: -------------------------------------------------------------------------------- 1 | package addtwonumbers 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestAddTwoNumbers(t *testing.T) { 8 | testCases := []struct { 9 | l1 *ListNode 10 | l2 *ListNode 11 | want *ListNode 12 | }{ 13 | { 14 | l1: &ListNode{0, nil}, 15 | l2: &ListNode{0, nil}, 16 | want: &ListNode{0, nil}, 17 | }, 18 | { 19 | l1: &ListNode{1, &ListNode{2, &ListNode{3, nil}}}, 20 | l2: &ListNode{1, &ListNode{2, &ListNode{3, nil}}}, 21 | want: &ListNode{2, &ListNode{4, &ListNode{6, nil}}}, 22 | }, 23 | { 24 | l1: &ListNode{1, &ListNode{2, &ListNode{3, nil}}}, 25 | l2: &ListNode{1, &ListNode{2, nil}}, 26 | want: &ListNode{2, &ListNode{4, &ListNode{3, nil}}}, 27 | }, 28 | { 29 | l1: &ListNode{1, &ListNode{6, &ListNode{4, nil}}}, 30 | l2: &ListNode{1, &ListNode{7, &ListNode{3, nil}}}, 31 | want: &ListNode{2, &ListNode{3, &ListNode{8, nil}}}, 32 | }, 33 | { 34 | l1: &ListNode{1, &ListNode{9, &ListNode{5, nil}}}, 35 | l2: &ListNode{1, &ListNode{2, nil}}, 36 | want: &ListNode{2, &ListNode{1, &ListNode{6, nil}}}, 37 | }, 38 | } 39 | 40 | for _, tc := range testCases { 41 | got := AddTwoNumbers(tc.l1, tc.l2) 42 | 43 | for got != nil || tc.want != nil { 44 | if got == nil || tc.want == nil || got.Val != tc.want.Val { 45 | t.Errorf("l1: %v\nl2: %v\ngot %v, want %v", tc.l1, tc.l2, got, tc.want) 46 | break 47 | } 48 | 49 | got = got.Next 50 | tc.want = tc.want.Next 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /linkedlist/designlinkedlist/ designlinkedlist.go: -------------------------------------------------------------------------------- 1 | package designlinkedlist 2 | 3 | type Node struct { 4 | Val int 5 | Next *Node 6 | } 7 | 8 | type MyLinkedList struct { 9 | Head *Node 10 | Tail *Node 11 | Length int 12 | } 13 | 14 | func Constructor() MyLinkedList { 15 | return MyLinkedList{Head: nil, 16 | Tail: nil, 17 | Length: 0} 18 | } 19 | 20 | //Get the value of the index-th node in the linked list. If the index is invalid, return -1. 21 | func (MyLinkedList *MyLinkedList) Get(index int) int { 22 | if index < 1 || index > MyLinkedList.Length { 23 | return -1 24 | } 25 | 26 | current := MyLinkedList.Head 27 | index-- 28 | 29 | for index > 0 { 30 | current = current.Next 31 | index-- 32 | } 33 | 34 | return current.Val 35 | } 36 | 37 | //AddAtHead a node of value val before the first element of the linked list. After the insertion, the new node will be the first node of the linked list. 38 | func (MyLinkedList *MyLinkedList) AddAtHead(val int) { 39 | newNode := &Node{Val: val, Next: MyLinkedList.Head} 40 | MyLinkedList.Head = newNode 41 | MyLinkedList.Length++ 42 | 43 | if MyLinkedList.Tail == nil { 44 | MyLinkedList.Tail = newNode 45 | } 46 | } 47 | 48 | //AddAtTail a node of value val to the last element of the linked list. 49 | func (MyLinkedList *MyLinkedList) AddAtTail(val int) { 50 | if MyLinkedList.Head == nil { 51 | MyLinkedList.AddAtHead(val) 52 | } else { 53 | newNode := &Node{Val: val} 54 | MyLinkedList.Tail.Next = newNode 55 | MyLinkedList.Tail = newNode 56 | MyLinkedList.Length++ 57 | } 58 | } 59 | 60 | //AddAtIndex a node of value val before the index-th node in the linked list. 61 | //If index equals to the length of linked list, the node will be appended to the end of linked list. 62 | //If index is greater than the length, the node will not be inserted. 63 | func (MyLinkedList *MyLinkedList) AddAtIndex(index int, val int) { 64 | if index > MyLinkedList.Length || index < 1 { 65 | return 66 | } 67 | 68 | if index == MyLinkedList.Length { 69 | MyLinkedList.AddAtTail(val) 70 | return 71 | } 72 | 73 | if index == 1 { 74 | MyLinkedList.AddAtHead(val) 75 | return 76 | } 77 | 78 | current := MyLinkedList.Head 79 | for 2 < index { 80 | current = current.Next 81 | index-- 82 | } 83 | 84 | newNode := &Node{Val: val, Next: current.Next} 85 | current.Next = newNode 86 | } 87 | 88 | //DeleteAtIndex the index-th node in the linked list, if the index is valid. 89 | func (MyLinkedList *MyLinkedList) DeleteAtIndex(index int) { 90 | if MyLinkedList == nil || index > MyLinkedList.Length || index < 1 { 91 | return 92 | } 93 | 94 | current := MyLinkedList.Head 95 | for index > 1 { 96 | current = current.Next 97 | index-- 98 | } 99 | 100 | current = current.Next 101 | MyLinkedList.Length-- 102 | } 103 | 104 | //707. Design Linked List 105 | //https://leetcode.com/problems/design-linked-list/ 106 | -------------------------------------------------------------------------------- /linkedlist/designlinkedlist/ designlinkedlist_test.go: -------------------------------------------------------------------------------- 1 | package designlinkedlist 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | type testCase struct { 8 | list MyLinkedList 9 | input int 10 | want *Node 11 | newLength int 12 | } 13 | 14 | func TestGet(t *testing.T) { 15 | list := Constructor() 16 | list.Head = &Node{Val: 1, Next: &Node{Val: 2, Next: &Node{Val: 3}}} 17 | list.Length = 3 18 | 19 | testCases := []struct { 20 | input int 21 | want int 22 | }{ 23 | { 24 | input: 1, 25 | want: 1, 26 | }, 27 | { 28 | input: 0, 29 | want: -1, 30 | }, 31 | { 32 | input: 1000, 33 | want: -1, 34 | }, 35 | { 36 | input: 3, 37 | want: 3, 38 | }, 39 | } 40 | 41 | for _, tc := range testCases { 42 | got := list.Get(tc.input) 43 | 44 | if got != tc.want { 45 | t.Errorf("input: %v - got: %d, want: %d", tc.input, got, tc.want) 46 | } 47 | } 48 | } 49 | 50 | func TestAddAtHead(t *testing.T) { 51 | list := Constructor() 52 | list.Head = &Node{Val: 1, Next: &Node{Val: 2, Next: &Node{Val: 3}}} 53 | list.Length = 3 54 | 55 | testCases := []testCase{ 56 | { 57 | input: 0, 58 | want: &Node{Val: 0, Next: &Node{Val: 1, Next: &Node{Val: 2, Next: &Node{Val: 3}}}}, 59 | newLength: 4, 60 | }, 61 | } 62 | 63 | for _, tc := range testCases { 64 | tc.list.AddAtHead(tc.input) 65 | current := tc.list.Head 66 | 67 | if !listsAreEqual(current, tc.list.Head) { 68 | t.Errorf("input: %v - got %v, want %v", tc.input, tc.list.Head, tc.want) 69 | } 70 | current = current.Next 71 | tc.want = tc.want.Next 72 | } 73 | } 74 | 75 | func TestAddAtTail(t *testing.T) { 76 | listWithElements := Constructor() 77 | listWithElements.AddAtHead(1) 78 | listWithElements.AddAtTail(2) 79 | listWithElements.AddAtTail(3) 80 | 81 | testCases := []testCase{ 82 | { 83 | list: Constructor(), 84 | input: 1, 85 | want: &Node{Val: 1}, 86 | newLength: 1, 87 | }, 88 | { 89 | list: listWithElements, 90 | input: 4, 91 | want: &Node{Val: 1, Next: &Node{Val: 2, Next: &Node{Val: 3, Next: &Node{Val: 4}}}}, 92 | newLength: 4, 93 | }, 94 | } 95 | 96 | for _, tc := range testCases { 97 | tc.list.AddAtTail(tc.input) 98 | current := tc.list.Head 99 | 100 | if !listsAreEqual(current, tc.list.Head) { 101 | t.Errorf("input: %v - got %v, want %v", tc.input, tc.list.Head, tc.want) 102 | } 103 | current = current.Next 104 | tc.want = tc.want.Next 105 | } 106 | } 107 | 108 | func TestAddAtIndex(t *testing.T) { 109 | listWithOneElement := Constructor() 110 | listWithOneElement.AddAtHead(2) 111 | 112 | listWithTwoElements := Constructor() 113 | listWithTwoElements.AddAtHead(1) 114 | listWithTwoElements.AddAtTail(2) 115 | 116 | listWitThreeElements := Constructor() 117 | listWitThreeElements.AddAtHead(1) 118 | listWitThreeElements.AddAtTail(3) 119 | listWitThreeElements.AddAtTail(4) 120 | 121 | listWitFourElements := Constructor() 122 | listWitFourElements.AddAtHead(1) 123 | listWitFourElements.AddAtTail(2) 124 | listWitFourElements.AddAtTail(3) 125 | listWitFourElements.AddAtTail(4) 126 | 127 | testCases := []struct { 128 | list MyLinkedList 129 | index int 130 | val int 131 | want *Node 132 | }{ 133 | { 134 | list: Constructor(), 135 | index: 1, 136 | val: 1, 137 | want: Constructor().Head, 138 | }, 139 | { 140 | list: listWithTwoElements, 141 | index: 2, 142 | val: 3, 143 | want: &Node{Val: 1, Next: &Node{Val: 2, Next: &Node{Val: 3}}}, 144 | }, 145 | { 146 | list: listWithOneElement, 147 | index: 1, 148 | val: 1, 149 | want: &Node{Val: 2, Next: &Node{Val: 1}}, 150 | }, 151 | { 152 | list: listWitThreeElements, 153 | index: 2, 154 | val: 2, 155 | want: &Node{Val: 1, Next: &Node{Val: 2, Next: &Node{Val: 3, Next: &Node{Val: 4}}}}, 156 | }, 157 | { 158 | list: listWitFourElements, 159 | index: 1, 160 | val: 0, 161 | want: &Node{Val: 0, Next: &Node{Val: 1, Next: &Node{Val: 2, Next: &Node{Val: 3, Next: &Node{Val: 4}}}}}, 162 | }, 163 | } 164 | 165 | for _, tc := range testCases { 166 | tc.list.AddAtIndex(tc.index, tc.val) 167 | 168 | if !listsAreEqual(tc.list.Head, tc.want) { 169 | t.Errorf("index: %d, val: %d - got: %v, want: %v", tc.index, tc.val, tc.list.Head, tc.want) 170 | } 171 | } 172 | } 173 | 174 | func TestDeleteAtIndex(t *testing.T) { 175 | listWithOneElement := Constructor() 176 | listWithOneElement.AddAtHead(2) 177 | 178 | listWithTwoElements := Constructor() 179 | listWithTwoElements.AddAtHead(1) 180 | listWithTwoElements.AddAtTail(2) 181 | 182 | listWitThreeElements := Constructor() 183 | listWitThreeElements.AddAtHead(1) 184 | listWitThreeElements.AddAtTail(2) 185 | listWitThreeElements.AddAtTail(3) 186 | 187 | testCases := []struct { 188 | list MyLinkedList 189 | index int 190 | want *Node 191 | }{ 192 | { 193 | list: listWithOneElement, 194 | index: 1, 195 | want: Constructor().Head, 196 | }, 197 | { 198 | list: listWithTwoElements, 199 | index: 2, 200 | want: &Node{Val: 1}, 201 | }, 202 | { 203 | list: listWitThreeElements, 204 | index: 2, 205 | want: &Node{Val: 1, Next: &Node{Val: 3}}, 206 | }, 207 | } 208 | 209 | for _, tc := range testCases { 210 | tc.list.DeleteAtIndex(tc.index) 211 | current := tc.list.Head 212 | 213 | if !listsAreEqual(current, tc.list.Head) { 214 | t.Errorf("list: %v, index: %d - got %v, want %v", tc.list, tc.index, tc.list.Head, tc.want) 215 | } 216 | } 217 | } 218 | 219 | func listsAreEqual(a *Node, b *Node) bool { 220 | for a != nil || b != nil { 221 | if a == nil || b == nil || a.Val != b.Val { 222 | return false 223 | } 224 | 225 | a = a.Next 226 | b = b.Next 227 | } 228 | return true 229 | } 230 | -------------------------------------------------------------------------------- /linkedlist/listnode/listnode.go: -------------------------------------------------------------------------------- 1 | package listnode 2 | 3 | //ListNode is a list node 4 | type ListNode struct { 5 | Val int 6 | Next *ListNode 7 | } 8 | -------------------------------------------------------------------------------- /linkedlist/removeduplicatesfromsortedlist/removeduplicatesfromsortedlist.go: -------------------------------------------------------------------------------- 1 | package removeduplicatesfromsortedlist 2 | 3 | import ln "github.com/wenndersantos/leetcode-in-go/linkedlist/listnode" 4 | 5 | //DeleteDuplicates executes in 6 | //Time: O(n) where n is the length of the linkedlist 7 | //Memory: O(1) 8 | func DeleteDuplicates(head *ln.ListNode) *ln.ListNode { 9 | if head == nil || head.Next == nil { 10 | return head 11 | } 12 | 13 | curr := head 14 | 15 | for curr != nil && curr.Next != nil { 16 | if curr.Val == curr.Next.Val { 17 | curr.Next = curr.Next.Next 18 | } else { 19 | curr = curr.Next 20 | } 21 | } 22 | 23 | return head 24 | } 25 | 26 | //83. Remove Duplicates from Sorted List 27 | //https://leetcode.com/problems/remove-duplicates-from-sorted-list/ 28 | -------------------------------------------------------------------------------- /linkedlist/removeduplicatesfromsortedlist/removeduplicatesfromsortedlist_test.go: -------------------------------------------------------------------------------- 1 | package removeduplicatesfromsortedlist 2 | 3 | import ( 4 | "testing" 5 | 6 | ln "github.com/wenndersantos/leetcode-in-go/linkedlist/listnode" 7 | ) 8 | 9 | func TestDeleteDuplicates(t *testing.T) { 10 | testCases := []struct { 11 | input *ln.ListNode 12 | want *ln.ListNode 13 | }{ 14 | { 15 | input: &ln.ListNode{}, 16 | want: &ln.ListNode{}, 17 | }, 18 | { 19 | input: &ln.ListNode{Val: 1, Next: nil}, 20 | want: &ln.ListNode{Val: 1, Next: nil}, 21 | }, 22 | { 23 | input: &ln.ListNode{Val: 1, Next: &ln.ListNode{Val: 1, Next: nil}}, 24 | want: &ln.ListNode{Val: 1, Next: nil}, 25 | }, 26 | { 27 | input: &ln.ListNode{Val: 1, Next: &ln.ListNode{Val: 2, Next: nil}}, 28 | want: &ln.ListNode{Val: 1, Next: &ln.ListNode{Val: 2, Next: nil}}, 29 | }, 30 | { 31 | input: &ln.ListNode{Val: 1, Next: &ln.ListNode{Val: 1, Next: &ln.ListNode{Val: 2, Next: nil}}}, 32 | want: &ln.ListNode{Val: 1, Next: &ln.ListNode{Val: 2, Next: nil}}, 33 | }, 34 | } 35 | 36 | for _, tc := range testCases { 37 | got := DeleteDuplicates(tc.input) 38 | 39 | for got != nil || tc.want != nil { 40 | if got == nil || tc.want == nil || got.Val != tc.want.Val { 41 | t.Errorf("input: %v - got %v, want %v", tc.input, got, tc.want) 42 | break 43 | } 44 | 45 | got = got.Next 46 | tc.want = tc.want.Next 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /linkedlist/reverselinkedlist/reverselinkedlist.go: -------------------------------------------------------------------------------- 1 | package reverselinkedlist 2 | 3 | import ln "github.com/wenndersantos/leetcode-in-go/linkedlist/listnode" 4 | 5 | //ReverseList executes in 6 | //Time: O(n) where n is the length of de list 7 | //Memory: O(1) reversed in place 8 | func ReverseList(head *ln.ListNode) *ln.ListNode { 9 | if head == nil { 10 | return head 11 | } 12 | 13 | current := head.Next 14 | head.Next = nil 15 | 16 | for current != nil { 17 | aux := current.Next 18 | current.Next = head 19 | 20 | head = current 21 | current = aux 22 | } 23 | 24 | return head 25 | } 26 | 27 | //206. Reverse Linked List 28 | //https://leetcode.com/problems/reverse-linked-list/ 29 | -------------------------------------------------------------------------------- /linkedlist/reverselinkedlist/reverselinkedlist_test.go: -------------------------------------------------------------------------------- 1 | package reverselinkedlist 2 | 3 | import ( 4 | "testing" 5 | 6 | ln "github.com/wenndersantos/leetcode-in-go/linkedlist/listnode" 7 | ) 8 | 9 | func TestReverseLinkedList(t *testing.T) { 10 | testCases := []struct { 11 | input *ln.ListNode 12 | want *ln.ListNode 13 | }{ 14 | { 15 | input: nil, 16 | want: nil, 17 | }, 18 | { 19 | input: &ln.ListNode{Val: 1, Next: nil}, 20 | want: &ln.ListNode{Val: 1, Next: nil}, 21 | }, 22 | { 23 | input: &ln.ListNode{Val: 1, Next: &ln.ListNode{Val: 9, Next: &ln.ListNode{Val: 5, Next: nil}}}, 24 | want: &ln.ListNode{Val: 5, Next: &ln.ListNode{Val: 9, Next: &ln.ListNode{Val: 1, Next: nil}}}, 25 | }, 26 | } 27 | 28 | for _, tc := range testCases { 29 | got := ReverseList(tc.input) 30 | 31 | for got != nil || tc.want != nil { 32 | if got == nil || tc.want == nil || got.Val != tc.want.Val { 33 | t.Errorf("input: %v - got %v, want %v", tc.input, got, tc.want) 34 | break 35 | } 36 | 37 | got = got.Next 38 | tc.want = tc.want.Next 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /strings/buddystrings/buddystrings.go: -------------------------------------------------------------------------------- 1 | package buddystrings 2 | 3 | //BuddyStrings executes in 4 | //Time: O(n) where n where is the length of A 5 | //Memory: O(1) 6 | func BuddyStrings(A string, B string) bool { 7 | if len(A) != len(B) { 8 | return false 9 | } 10 | 11 | memory := [26]int{} 12 | firstIdx, secondIdx := -1, -1 13 | 14 | if A == B { 15 | for _, val := range A { 16 | memory[val-'a']++ 17 | 18 | if memory[val-'a'] > 1 { 19 | return true 20 | } 21 | } 22 | } else { 23 | for i := 0; i < len(A); i++ { 24 | if A[i] != B[i] { 25 | if firstIdx == -1 { 26 | firstIdx = i 27 | } else if secondIdx == -1 { 28 | secondIdx = i 29 | } else { // more than 1 swap 30 | return false 31 | } 32 | } 33 | } 34 | 35 | } 36 | return secondIdx != -1 && A[firstIdx] == B[secondIdx] && A[secondIdx] == B[firstIdx] 37 | } 38 | 39 | //859. Buddy Strings 40 | //https://leetcode.com/problems/buddy-strings/ 41 | -------------------------------------------------------------------------------- /strings/buddystrings/buddystrings_test.go: -------------------------------------------------------------------------------- 1 | package buddystrings 2 | 3 | import "testing" 4 | 5 | func TestBuddyStrings(t *testing.T) { 6 | testCases := []struct { 7 | str1 string 8 | str2 string 9 | want bool 10 | }{ 11 | { 12 | str1: "ab", 13 | str2: "ba", 14 | want: true, 15 | }, 16 | { 17 | str1: "ab", 18 | str2: "ab", 19 | want: false, 20 | }, 21 | { 22 | str1: "aa", 23 | str2: "aa", 24 | want: true, 25 | }, 26 | { 27 | str1: "aaaaaaabc", 28 | str2: "aaaaaaacb", 29 | want: true, 30 | }, 31 | { 32 | str1: "", 33 | str2: "aa", 34 | want: false, 35 | }, 36 | { 37 | str1: "aa", 38 | str2: "", 39 | want: false, 40 | }, 41 | { 42 | str1: "abcaa", 43 | str2: "abcbb", 44 | want: false, 45 | }, 46 | } 47 | 48 | for _, tc := range testCases { 49 | got := BuddyStrings(tc.str1, tc.str2) 50 | 51 | if got != tc.want { 52 | t.Errorf("str1: %s, str2: %s - got: %t, want: %t", tc.str1, tc.str2, got, tc.want) 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /strings/detectcapitaluse/detectcapitaluse.go: -------------------------------------------------------------------------------- 1 | package detectcapitaluse 2 | 3 | //DetectCapitalUse executes in 4 | //Time: O(n) 5 | //Memory: O(1) 6 | func DetectCapitalUse(word string) bool { 7 | foundNonCapital := false 8 | countCapitals := 0 9 | 10 | for i, val := range word { 11 | if val >= 65 && val <= 90 { 12 | if i > 0 && foundNonCapital { 13 | return false 14 | } 15 | 16 | countCapitals++ 17 | } else { 18 | if countCapitals > 1 { 19 | return false 20 | } 21 | 22 | foundNonCapital = true 23 | } 24 | } 25 | 26 | return true 27 | } 28 | 29 | //520. Detect Capital 30 | //https://leetcode.com/problems/detect-capital/submissions/ 31 | -------------------------------------------------------------------------------- /strings/detectcapitaluse/detectcapitaluse_test.go: -------------------------------------------------------------------------------- 1 | package detectcapitaluse 2 | 3 | import "testing" 4 | 5 | func TestDetectCapitalUse(t *testing.T) { 6 | testCases := []struct { 7 | input string 8 | want bool 9 | }{ 10 | { 11 | input: "foobar", 12 | want: true, 13 | }, 14 | { 15 | input: "FOOBAR", 16 | want: true, 17 | }, 18 | { 19 | input: "Foobar", 20 | want: true, 21 | }, 22 | { 23 | input: "foobaR", 24 | want: false, 25 | }, 26 | { 27 | input: "fooBar", 28 | want: false, 29 | }, 30 | } 31 | 32 | for _, tc := range testCases { 33 | got := DetectCapitalUse(tc.input) 34 | 35 | if got != tc.want { 36 | t.Errorf("input: %v - got %t, want %t", tc.input, got, tc.want) 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /strings/findcommonchars/findcommonchars.go: -------------------------------------------------------------------------------- 1 | package findcommonchars 2 | 3 | //CommonChars executes in 4 | //Time: O(n^2) 5 | //Memory: O(1) - Three fixed size array [26]int 6 | func CommonChars(A []string) []string { 7 | toCompare := [26]int{} 8 | 9 | for _, c := range A[0] { 10 | toCompare[c-'a']++ 11 | } 12 | 13 | for i := 1; i < len(A); i++ { 14 | countCurrentWord := [26]int{} 15 | 16 | for _, c := range A[i] { 17 | countCurrentWord[c-'a']++ 18 | } 19 | 20 | for j := 0; j < 26; j++ { 21 | if countCurrentWord[j] < toCompare[j] { 22 | toCompare[j] = countCurrentWord[j] 23 | } 24 | } 25 | } 26 | 27 | result := make([]string, 100) 28 | resultIndex := 0 29 | 30 | for i := 0; i < 26; i++ { 31 | for j := 0; j < toCompare[i]; j++ { 32 | result[resultIndex] = string('a' + i) 33 | resultIndex++ 34 | } 35 | } 36 | 37 | return result[:resultIndex] 38 | } 39 | 40 | //1002. Find Common Characters 41 | //https://leetcode.com/problems/find-common-characters/ 42 | -------------------------------------------------------------------------------- /strings/findcommonchars/findcommonchars_test.go: -------------------------------------------------------------------------------- 1 | package findcommonchars 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/wenndersantos/leetcode-in-go/testutils" 7 | ) 8 | 9 | func TestFindCommonChars(t *testing.T) { 10 | testCases := []struct { 11 | input []string 12 | want []string 13 | }{ 14 | { 15 | input: []string{"bella", "label", "roller"}, 16 | want: []string{"e", "l", "l"}, 17 | }, 18 | { 19 | input: []string{"cool", "lock", "cook"}, 20 | want: []string{"c", "o"}, 21 | }, 22 | } 23 | 24 | for _, tc := range testCases { 25 | got := CommonChars(tc.input) 26 | 27 | if !testutils.StringSliceAreEqual(got, tc.want) { 28 | t.Errorf("input: %v - got: %v, want: %v.", tc.input, got, tc.want) 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /strings/jewelsandstones/jewelsandstones.go: -------------------------------------------------------------------------------- 1 | package jewelsandstones 2 | 3 | //NumJewelsInStones executes in 4 | //Time: O(j+s) 5 | //Memory: O(1) - fixed size array [256] bool 6 | func NumJewelsInStones(J string, S string) int { 7 | jewels := [256]bool{} 8 | for _, c := range J { 9 | jewels[c] = true 10 | } 11 | 12 | result := 0 13 | for _, c := range S { 14 | if jewels[c] { 15 | result++ 16 | } 17 | } 18 | return result 19 | } 20 | 21 | //771. Jewels and Stones 22 | //https://leetcode.com/problems/jewels-and-stones/ 23 | -------------------------------------------------------------------------------- /strings/jewelsandstones/jewelsandstones_test.go: -------------------------------------------------------------------------------- 1 | package jewelsandstones 2 | 3 | import "testing" 4 | 5 | func TestNumJewelsInStones(t *testing.T) { 6 | testCases := []struct { 7 | jewels string 8 | myStones string 9 | want int 10 | }{ 11 | { 12 | jewels: "aA", 13 | myStones: "aAAbbbb", 14 | want: 3, 15 | }, 16 | { 17 | jewels: "z", 18 | myStones: "ZZ", 19 | want: 0, 20 | }, 21 | } 22 | 23 | for _, tc := range testCases { 24 | got := NumJewelsInStones(tc.jewels, tc.myStones) 25 | 26 | if got != tc.want { 27 | t.Errorf("jewels: %s, myStones: %s - got: %d, want: %d", tc.jewels, tc.myStones, got, tc.want) 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /strings/lengthoflongestsubstring/lengthoflongestsubstring.go: -------------------------------------------------------------------------------- 1 | package lengthoflongestsubstring 2 | 3 | //LengthOfLongestSubstring executes in 4 | //Time: O(n) - where n is the length of s 5 | //Memory: O(1) - using a fixed size [256]int 6 | func LengthOfLongestSubstring(s string) int { 7 | result, l, r, buffer := 0, 0, 0, [256]int{} 8 | 9 | for r < len(s) { 10 | if buffer[s[r]] > 0 { 11 | if l < buffer[s[r]] { 12 | l = buffer[s[r]] 13 | } 14 | } 15 | 16 | if r-l+1 > result { 17 | result = r - l + 1 18 | } 19 | 20 | buffer[s[r]] = r + 1 21 | r++ 22 | } 23 | return result 24 | } 25 | 26 | //3. Longest Substring Without Repeating Characters 27 | //https://leetcode.com/problems/longest-substring-without-repeating-characters/ 28 | -------------------------------------------------------------------------------- /strings/lengthoflongestsubstring/lengthoflongestsubstring_test.go: -------------------------------------------------------------------------------- 1 | package lengthoflongestsubstring 2 | 3 | import "testing" 4 | 5 | func TestLengthOfLongestSubstring(t *testing.T) { 6 | testCases := []struct { 7 | input string 8 | want int 9 | }{ 10 | { 11 | input: "", 12 | want: 0, 13 | }, 14 | { 15 | input: "a", 16 | want: 1, 17 | }, 18 | { 19 | input: "abcabcbb", 20 | want: 3, 21 | }, 22 | { 23 | input: "bbbbb", 24 | want: 1, 25 | }, 26 | { 27 | input: "pwwkew", 28 | want: 3, 29 | }, 30 | { 31 | input: "dvdf", 32 | want: 3, 33 | }, 34 | { 35 | input: "tmmzuxt", 36 | want: 5, 37 | }, 38 | } 39 | 40 | for _, tc := range testCases { 41 | got := LengthOfLongestSubstring(tc.input) 42 | 43 | if got != tc.want { 44 | t.Errorf("input: %s - got: %d, want: %d", tc.input, got, tc.want) 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /strings/maxoccurringchar/maxoccurringchar.go: -------------------------------------------------------------------------------- 1 | package maxoccurringchar 2 | 3 | //MaxOccurringChar executes in 4 | //Time: O(n) where n is the length of the input. 5 | //Memory: O(1) - Always alocating a fixed size hashmap 6 | //doesn't matter length of n 7 | func MaxOccurringChar(text string) string { 8 | result := "" 9 | 10 | if len(text) == 0 { 11 | return result 12 | } 13 | 14 | memory := make(map[rune]int, 62) 15 | max := 0 16 | 17 | for _, char := range text { 18 | if _, ok := memory[char]; ok { 19 | memory[char]++ 20 | } else { 21 | memory[char] = 1 22 | } 23 | 24 | if memory[char] > max { 25 | result = string(char) 26 | max = memory[char] 27 | } 28 | } 29 | 30 | return result 31 | } 32 | -------------------------------------------------------------------------------- /strings/maxoccurringchar/maxoccurringchar_test.go: -------------------------------------------------------------------------------- 1 | package maxoccurringchar 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestMaxOccurringChar(t *testing.T) { 8 | cases := []struct { 9 | text string 10 | want string 11 | }{ 12 | {"abc", "a"}, 13 | {"aabc", "a"}, 14 | {"aabccoc", "c"}, 15 | {"aaaccc", "a"}, 16 | } 17 | 18 | for _, testcase := range cases { 19 | got := MaxOccurringChar(testcase.text) 20 | 21 | if got != testcase.want { 22 | t.Errorf("got: %s, want: %s.", got, testcase.want) 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /strings/numberofsegmentsinastring/numberofsegmentsinastring.go: -------------------------------------------------------------------------------- 1 | package numberofsegmentsinastring 2 | 3 | //CountSegments executes in 4 | //Time: O(n) - where n is the length of s 5 | //Memory: O(1) 6 | func CountSegments(s string) int { 7 | segments := 0 8 | 9 | for i, val := range s { 10 | if val != ' ' && (i == 0 || s[i-1] == ' ') { 11 | segments++ 12 | } 13 | } 14 | return segments 15 | } 16 | 17 | //434. Number of Segments in a String 18 | //https://leetcode.com/problems/number-of-segments-in-a-string/ 19 | -------------------------------------------------------------------------------- /strings/numberofsegmentsinastring/numberofsegmentsinastring_test.go: -------------------------------------------------------------------------------- 1 | package numberofsegmentsinastring 2 | 3 | import "testing" 4 | 5 | func TestCountSegments(t *testing.T) { 6 | testCases := []struct { 7 | input string 8 | want int 9 | }{ 10 | { 11 | input: "", 12 | want: 0, 13 | }, 14 | { 15 | input: " ", 16 | want: 0, 17 | }, 18 | { 19 | input: "Hello, my name is John", 20 | want: 5, 21 | }, 22 | { 23 | input: "Hi there!", 24 | want: 2, 25 | }, 26 | { 27 | input: "Of all the gin joints in all the towns in all the world, ", 28 | want: 13, 29 | }, 30 | { 31 | input: ", , , , a, eaefa", 32 | want: 6, 33 | }, 34 | } 35 | 36 | for _, tc := range testCases { 37 | got := CountSegments(tc.input) 38 | 39 | if got != tc.want { 40 | t.Errorf("input: %s - got: %d, want: %d", tc.input, got, tc.want) 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /strings/reverseonlyletters/reverse_only_letters.go: -------------------------------------------------------------------------------- 1 | package reverseonlyletters 2 | 3 | func isLetter(asciiChar rune) bool { 4 | return asciiChar >= 'a' && asciiChar <= 'z' || asciiChar >= 'A' && asciiChar <= 'Z' 5 | } 6 | 7 | //ReverseOnlyLetters executes in 8 | //Time: O(n) 9 | //Memory: O(1) using two pointers (low and high) approach 10 | func ReverseOnlyLetters(S string) string { 11 | i, j, str := 0, len(S)-1, []rune(S) 12 | 13 | for i < j { 14 | if !isLetter(str[i]) { 15 | i++ 16 | continue 17 | } 18 | 19 | if !isLetter(str[j]) { 20 | j-- 21 | continue 22 | } 23 | 24 | str[i], str[j] = str[j], str[i] 25 | i++ 26 | j-- 27 | } 28 | 29 | return string(str) 30 | } 31 | 32 | //917. Reverse Only Letters 33 | //https://leetcode.com/problems/reverse-only-letters/ 34 | -------------------------------------------------------------------------------- /strings/reverseonlyletters/reverseonlyletters_test.go: -------------------------------------------------------------------------------- 1 | package reverseonlyletters 2 | 3 | import "testing" 4 | 5 | func TestReverseOnlyLetters(t *testing.T) { 6 | testCases := []struct { 7 | input string 8 | want string 9 | }{ 10 | { 11 | input: "ab-cd", 12 | want: "dc-ba", 13 | }, 14 | { 15 | input: "a-bC-dEf-ghIj", 16 | want: "j-Ih-gfE-dCba", 17 | }, 18 | { 19 | input: "Test1ng-Leet=code-Q!", 20 | want: "Qedo1ct-eeLg=ntse-T!", 21 | }, 22 | } 23 | 24 | for _, tc := range testCases { 25 | got := ReverseOnlyLetters(tc.input) 26 | 27 | if got != tc.want { 28 | t.Errorf("input: %s - got: %s, want: %s.", tc.input, got, tc.want) 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /strings/reversevowels/reversevowels.go: -------------------------------------------------------------------------------- 1 | package reversevowels 2 | 3 | import "strings" 4 | 5 | func isVowel(c rune) bool { 6 | vowels := "aeiouAEIOU" 7 | 8 | return strings.ContainsRune(vowels, c) 9 | } 10 | 11 | //ReverseVowels executes in 12 | //Time: O(n) - where n is the length of s. In the worst case, there is no vowel 13 | //Memory: O(1) 14 | func ReverseVowels(s string) string { 15 | i, j, result := 0, len(s)-1, []rune(s) 16 | 17 | for i < j { 18 | for i < j && !isVowel(result[i]) { 19 | i++ 20 | } 21 | for i < j && !isVowel(result[j]) { 22 | j-- 23 | } 24 | result[j], result[i] = result[i], result[j] 25 | j-- 26 | i++ 27 | } 28 | 29 | return string(result) 30 | } 31 | 32 | //345. Reverse Vowels of a String 33 | //https://leetcode.com/problems/reverse-vowels-of-a-string/ 34 | -------------------------------------------------------------------------------- /strings/reversevowels/reversevowels_test.go: -------------------------------------------------------------------------------- 1 | package reversevowels 2 | 3 | import "testing" 4 | 5 | func TestReverseVowels(t *testing.T) { 6 | testCases := []struct { 7 | input string 8 | want string 9 | }{ 10 | { 11 | input: "", 12 | want: "", 13 | }, 14 | { 15 | input: "p", 16 | want: "p", 17 | }, 18 | { 19 | input: "po", 20 | want: "po", 21 | }, 22 | { 23 | input: "Aa", 24 | want: "aA", 25 | }, 26 | { 27 | input: "hello", 28 | want: "holle", 29 | }, 30 | { 31 | input: "leetcode", 32 | want: "leotcede", 33 | }, 34 | } 35 | 36 | for _, tc := range testCases { 37 | got := ReverseVowels(tc.input) 38 | 39 | if got != tc.want { 40 | t.Errorf("input: %s - got: %s, want: %s", tc.input, got, tc.want) 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /strings/reversewordsinastringiii/reversewordsinastringiii.go: -------------------------------------------------------------------------------- 1 | package reversewordsinastringiii 2 | 3 | //ReverseWords executes in 4 | //Time: O(n * m) where N is the length of string and m is the length of the biggest word 5 | //Memory: O(n) wheren n is result. (should I consider?) 6 | func ReverseWords(s string) string { 7 | if len(s) <= 1 { 8 | return s 9 | } 10 | 11 | i, j, result := 0, 0, []byte(s) 12 | 13 | for j <= len(s) { 14 | if j == len(s) && i < j || s[j] == ' ' { 15 | aux := j - 1 16 | for aux > i { 17 | result[i], result[aux] = s[aux], s[i] 18 | aux-- 19 | i++ 20 | } 21 | i = j + 1 22 | } 23 | j++ 24 | } 25 | 26 | return string(result) 27 | } 28 | 29 | //557. Reverse Words in a String III 30 | //https://leetcode.com/problems/reverse-words-in-a-string-iii/ 31 | -------------------------------------------------------------------------------- /strings/reversewordsinastringiii/reversewordsinastringiii_test.go: -------------------------------------------------------------------------------- 1 | package reversewordsinastringiii 2 | 3 | import "testing" 4 | 5 | func TestReverseWords(t *testing.T) { 6 | testCases := []struct { 7 | input string 8 | want string 9 | }{ 10 | { 11 | input: "Let's take LeetCode contest", 12 | want: "s'teL ekat edoCteeL tsetnoc", 13 | }, 14 | { 15 | input: "p", 16 | want: "p", 17 | }, 18 | { 19 | input: "", 20 | want: "", 21 | }, 22 | } 23 | 24 | for _, tc := range testCases { 25 | got := ReverseWords(tc.input) 26 | 27 | if got != tc.want { 28 | t.Errorf("input: %s\ngot: %s\nwant: %s", tc.input, got, tc.want) 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /strings/singlerowkeyboard/singlerowkeyboard.go: -------------------------------------------------------------------------------- 1 | package singlerowkeyboard 2 | 3 | //CalculateTime executes in 4 | //Time: O(n) where n is the length of word. Assuming keyboard will always have a fixed length 5 | //Memory:O(1) - Assuming keyboard will always have a fixed length 6 | func CalculateTime(keyboard string, word string) int { 7 | k := make(map[rune]int, len(keyboard)) 8 | for i, c := range keyboard { 9 | k[c] = i 10 | } 11 | 12 | result, lastIndex := 0, 0 13 | for _, c := range word { 14 | diff := lastIndex - k[c] 15 | if diff < 0 { 16 | diff *= -1 17 | } 18 | result += diff 19 | lastIndex = k[c] 20 | } 21 | return result 22 | } 23 | 24 | //1165. Single-Row Keyboard 25 | //https://leetcode.com/problems/single-row-keyboard/ 26 | -------------------------------------------------------------------------------- /strings/singlerowkeyboard/singlerowkeyboard_test.go: -------------------------------------------------------------------------------- 1 | package singlerowkeyboard 2 | 3 | import "testing" 4 | 5 | func TestCalculateTime(t *testing.T) { 6 | testCases := []struct { 7 | keyboard string 8 | word string 9 | want int 10 | }{ 11 | { 12 | keyboard: "abcdefghijklmnopqrstuvwxyz", 13 | word: "cba", 14 | want: 4, 15 | }, 16 | { 17 | keyboard: "pqrstuvwxyzabcdefghijklmno", 18 | word: "leetcode", 19 | want: 73, 20 | }, 21 | } 22 | 23 | for _, tc := range testCases { 24 | got := CalculateTime(tc.keyboard, tc.word) 25 | 26 | if got != tc.want { 27 | t.Errorf("keyboard: %s, word: %s - got: %d, want: %d", tc.keyboard, tc.word, got, tc.want) 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /strings/validparentheses/validparentheses.go: -------------------------------------------------------------------------------- 1 | package validparentheses 2 | 3 | //IsValid executes in 4 | //Time: O(n) - where n is the length of the input 5 | //Memory: O(1) - I am using a fixed size stack, 6 | //but would be better to use one with variable 7 | //length which would result in O(n) memory 8 | func IsValid(s string) bool { 9 | if len(s) == 1 { 10 | return false 11 | } 12 | 13 | stack, topIndex := [100]rune{}, -1 14 | kv := map[rune]rune{ 15 | ')': '(', 16 | ']': '[', 17 | '}': '{', 18 | } 19 | 20 | for _, val := range s { 21 | switch val { 22 | case '(', '{', '[': 23 | topIndex++ 24 | stack[topIndex] = val 25 | case ')', '}', ']': 26 | if topIndex == -1 || stack[topIndex] != kv[val] { 27 | return false 28 | } 29 | topIndex-- 30 | } 31 | } 32 | return topIndex == -1 33 | } 34 | 35 | //20. Valid Parentheses 36 | //https://leetcode.com/problems/valid-parentheses/ 37 | -------------------------------------------------------------------------------- /strings/validparentheses/validparentheses_test.go: -------------------------------------------------------------------------------- 1 | package validparentheses 2 | 3 | import "testing" 4 | 5 | func TestIsValid(t *testing.T) { 6 | testCases := []struct { 7 | input string 8 | want bool 9 | }{ 10 | { 11 | input: "", 12 | want: true, 13 | }, 14 | { 15 | input: "]", 16 | want: false, 17 | }, 18 | { 19 | input: "){", 20 | want: false, 21 | }, 22 | { 23 | input: "[])", 24 | want: false, 25 | }, 26 | { 27 | input: "()", 28 | want: true, 29 | }, 30 | { 31 | input: "()[]{}", 32 | want: true, 33 | }, 34 | { 35 | input: "(]", 36 | want: false, 37 | }, 38 | { 39 | input: "([)]", 40 | want: false, 41 | }, 42 | { 43 | input: "{[]}", 44 | want: true, 45 | }, 46 | } 47 | 48 | for _, tc := range testCases { 49 | got := IsValid(tc.input) 50 | 51 | if got != tc.want { 52 | t.Errorf("input: %s - got: %t, want: %t", tc.input, got, tc.want) 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /testutils/testutils.go: -------------------------------------------------------------------------------- 1 | package testutils 2 | 3 | //IntSliceAreEqual foo 4 | func IntSliceAreEqual(a []int, b []int) bool { 5 | if len(a) != len(b) { 6 | return false 7 | } 8 | 9 | for i, j := 0, 0; i < len(a); i, j = i+1, j+1 { 10 | if a[i] != b[j] { 11 | return false 12 | } 13 | } 14 | 15 | return true 16 | } 17 | 18 | //StringSliceAreEqual foo 19 | func StringSliceAreEqual(a []string, b []string) bool { 20 | if len(a) != len(b) { 21 | return false 22 | } 23 | 24 | for i, j := 0, 0; i < len(a); i, j = i+1, j+1 { 25 | if a[i] != b[j] { 26 | return false 27 | } 28 | } 29 | 30 | return true 31 | } 32 | --------------------------------------------------------------------------------