├── 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 |
- All About Birds
2 |
- Kinds of Birds
3 |
- The Finch
4 |
5 | - The Swan
6 |
7 | - Habitats
8 |
- 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 |
--------------------------------------------------------------------------------