├── InsertionSort.go ├── SelectionSort.go ├── README.md ├── quicksort.go ├── stringpermswithdups.go ├── minKelements.go ├── mergesort.go ├── Binarysearch.go ├── main.go ├── StringCombinations.go ├── countlongestsequence.go └── StringPermutation.go /InsertionSort.go: -------------------------------------------------------------------------------- 1 | /* 2 | Insertion sort implementation in Go 3 | */ 4 | package main 5 | 6 | func InsertionSort(myArray []int) { 7 | for i := 1; i < len(myArray); i++ { 8 | val := myArray[i] 9 | j := i - 1 10 | for j >= 0 && val < myArray[j] { 11 | myArray[j+1] = myArray[j] 12 | j-- 13 | } 14 | myArray[j+1] = val 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /SelectionSort.go: -------------------------------------------------------------------------------- 1 | /* 2 | Selection sort implementation in Go 3 | */ 4 | package main 5 | 6 | func findMinimumIndex(array []int, startIndex int) int { 7 | if startIndex > len(array)-1 { 8 | return -1 9 | } 10 | retVal := startIndex 11 | min := array[startIndex] 12 | for i := startIndex + 1; i <= len(array)-1; i++ { 13 | if min > array[i] { 14 | min = array[i] 15 | retVal = i 16 | } 17 | } 18 | return retVal 19 | } 20 | 21 | func selectionSort(myArray []int) { 22 | for i := 0; i <= len(myArray)-1; i++ { 23 | m := findMinimumIndex(myArray, i) 24 | temp := myArray[i] 25 | myArray[i] = myArray[m] 26 | myArray[m] = temp 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Algorithms 2 | 3 | Some programming Algorithms and exercises implemented in Go. Great for learning Go and comparing with other languages. For more of my articles, check www.minaandrawos.com. 4 | 5 | My Go video courses: 6 | - Modern Go Programming: https://www.udemy.com/modern-golang-programming/ , covers how to write modern software in the Go language 7 | - Mastering Go Programming: https://www.udemy.com/mastering-go-programming , covers advanced topics about the Go language 8 | 9 | 10 | My Go book: 11 | - Cloud Native programming with Go: https://www.amazon.com/dp/B072J4BWX1/ , covers how to write distributed cloud native applications in the Go language 12 | -------------------------------------------------------------------------------- /quicksort.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | func quickSort(input []int, left, right int) { 4 | index := partition(input, left, right) 5 | if index-1 > left { 6 | quickSort(input, left, index-1) 7 | } 8 | if index < right { 9 | quickSort(input, index, right) 10 | } 11 | } 12 | 13 | func partition(input []int, left, right int) int { 14 | pivot := input[(left+right)/2] 15 | for left <= right { 16 | for pivot > input[left] { 17 | left++ 18 | } 19 | 20 | for pivot < input[right] { 21 | right-- 22 | } 23 | 24 | if left <= right { 25 | temp := input[left] 26 | input[left] = input[right] 27 | input[right] = temp 28 | left++ 29 | right-- 30 | } 31 | } 32 | return left 33 | } 34 | -------------------------------------------------------------------------------- /stringpermswithdups.go: -------------------------------------------------------------------------------- 1 | /* 2 | Find all the permutations of a string that has duplicate characters, ensure that no permutation is repeated twice 3 | */ 4 | package main 5 | 6 | import "fmt" 7 | 8 | func main() { 9 | freq := make(map[byte]int) 10 | input := "122" 11 | for _, v := range input { 12 | freq[byte(v)]++ 13 | } 14 | permsWithDuplicates(input, []byte{}, freq) 15 | } 16 | 17 | func permsWithDuplicates(input string, subset []byte, freqtable map[byte]int) { 18 | if len(subset) >= len(input) { 19 | fmt.Println(string(subset)) 20 | return 21 | } 22 | 23 | for k := range freqtable { 24 | count := freqtable[k] 25 | if count > 0 { 26 | freqtable[k] = count - 1 27 | permsWithDuplicates(input, append(subset, k), freqtable) 28 | freqtable[k] = count 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /minKelements.go: -------------------------------------------------------------------------------- 1 | /* 2 | This algorithms can retrieve the minimum k elements of an array, it runs at O(KN) time. 3 | */ 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "math" 9 | ) 10 | 11 | func main() { 12 | result := getTopK([]int{8, 9, 10, 11, 32, 44, 2, 1, 4}, 6) 13 | fmt.Println(result) 14 | } 15 | 16 | func getTopK(array []int, k int) []int { 17 | result := make([]int, k) 18 | for i := range result { 19 | result[i] = math.MaxInt64 20 | } 21 | 22 | for _, v := range array { 23 | current := v 24 | for i := 0; i < k; i++ { 25 | if result[i] == math.MaxInt64 { 26 | result[i] = current 27 | break 28 | } 29 | 30 | if result[i] > current { 31 | temp := result[i] 32 | result[i] = current 33 | current = temp 34 | } 35 | } 36 | } 37 | return result 38 | } 39 | -------------------------------------------------------------------------------- /mergesort.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | func main() { 4 | 5 | } 6 | 7 | func mergesort(array, helper []int, start, end int) { 8 | if start >= end { 9 | return 10 | } 11 | mid := (start + end) / 2 12 | merge(array, helper, start, mid) 13 | merge(array, helper, mid, end) 14 | } 15 | 16 | func merge(array, helper []int, start, end int) { 17 | for i, v := range array { 18 | helper[i] = v 19 | } 20 | 21 | middle := (start + end) / 2 22 | current := start 23 | right := middle + 1 24 | for start <= middle && right < end { 25 | if helper[start] <= helper[right] { 26 | array[current] = helper[start] 27 | start++ 28 | } else if helper[right] > helper[start] { 29 | array[current] = helper[right] 30 | right++ 31 | } 32 | current++ 33 | } 34 | 35 | remaining := middle - start 36 | for i := 0; i < remaining; i++ { 37 | array[i+current] = helper[start+i] 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Binarysearch.go: -------------------------------------------------------------------------------- 1 | /* 2 | Binary search implementation in Go 3 | */ 4 | package main 5 | 6 | func binarySearch(array []int, target int, lowIndex int, highIndex int) int { 7 | if highIndex < lowIndex { 8 | return -1 9 | } 10 | mid := int((lowIndex + highIndex) / 2) 11 | if array[mid] > target { 12 | return binarySearch(array, target, lowIndex, mid) 13 | } else if array[mid] < target { 14 | return binarySearch(array, target, mid+1, highIndex) 15 | } else { 16 | return mid 17 | } 18 | } 19 | 20 | func iterBinarySearch(array []int, target int, lowIndex int, highIndex int) int { 21 | startIndex := lowIndex 22 | endIndex := highIndex 23 | var mid int 24 | for startIndex < endIndex { 25 | mid = int((startIndex + endIndex) / 2) 26 | if array[mid] > target { 27 | endIndex = mid 28 | } else if array[mid] < target { 29 | startIndex = mid 30 | } else { 31 | return mid 32 | } 33 | } 34 | return -1 35 | } 36 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | /* 2 | A collection of algorithms implemented in Go 3 | */ 4 | package main 5 | 6 | import "fmt" 7 | 8 | func main() { 9 | //BinarySearch 10 | array := []int{1, 2, 3, 4, 5, 6, 6, 10, 15, 15, 17, 18, 19, 30} 11 | find := binarySearch(array, 10, 0, len(array)-1) 12 | fmt.Printf("Found the element by recursive binary search at index %d \n", find) 13 | find = iterBinarySearch(array, 10, 0, len(array)-1) 14 | fmt.Printf("Found the element by iterative binary search at index %d \n", find) 15 | 16 | //String permutation 17 | input := "hat" 18 | startPermutation(input) 19 | 20 | //String combinations 21 | input = "wxyz" 22 | startCombinations(input) 23 | 24 | //Selection sort 25 | array = []int{7, 1, 9, 0, 2, 14, 10, 11, 4, 13} 26 | fmt.Printf("Array before sorting %v \n", array) 27 | selectionSort(array) 28 | fmt.Printf("Selection sorted array %v \n", array) 29 | 30 | //Insertion sort 31 | array = []int{7, 1, 9, 0, 2, 14, 10, 11, 4, 13} 32 | fmt.Printf("Array before sorting %v \n", array) 33 | InsertionSort(array) 34 | fmt.Printf("Insertion sorted array %v \n", array) 35 | } 36 | -------------------------------------------------------------------------------- /StringCombinations.go: -------------------------------------------------------------------------------- 1 | /* 2 | String combinations in Go 3 | 4 | This is an exercise of recursion typically covered in programming training books: 5 | PROBLEM: Implement a function that prints all possible combinations of the 6 | characters in a string. These combinations range in length from one to the length 7 | of the string. Two combinations that differ only in ordering of their characters are 8 | the same combination. In other words, “12” and “31” are different combinations 9 | from the input string “123”, but “21” is the same as “12”. 10 | 11 | */ 12 | package main 13 | 14 | import "fmt" 15 | 16 | type Combinations struct { 17 | out []rune 18 | in []rune 19 | } 20 | 21 | func startCombinations(input string) { 22 | c := &Combinations{ 23 | in: []rune(input), 24 | } 25 | 26 | c.Combine(0) 27 | } 28 | 29 | func (c *Combinations) Combine(seed int) { 30 | inLen := len(c.in) 31 | for i := seed; i < inLen-1; i++ { 32 | c.out = append(c.out, c.in[i]) 33 | fmt.Println(string(c.out)) 34 | c.Combine(i + 1) 35 | c.out = c.out[:len(c.out)-1] 36 | } 37 | c.out = append(c.out, c.in[inLen-1]) 38 | fmt.Println(string(c.out)) 39 | c.out = c.out[:len(c.out)-1] 40 | } 41 | -------------------------------------------------------------------------------- /countlongestsequence.go: -------------------------------------------------------------------------------- 1 | /* 2 | Given an unsorted array, count the longest occuring sequence in the array. In the example below, the count is 4 => 1,2,3,4 3 | This algorithm builds a graph then counts the longest branch, it runs in O(N) time 4 | */ 5 | package main 6 | 7 | import ( 8 | "fmt" 9 | "math" 10 | ) 11 | 12 | func main() { 13 | fmt.Println(buildGraph([]int{100, 4, 200, 1, 3, 2})) 14 | } 15 | 16 | func buildGraph(values []int) int { 17 | m := make(map[int]*Node) 18 | for _, v := range values { 19 | m[v] = &Node{value: v} 20 | } 21 | g := Graph{} 22 | for k := range m { 23 | if node, ok := m[k+1]; ok { 24 | m[k].child = node 25 | } 26 | if _, ok := m[k-1]; !ok { 27 | g.parents = append(g.parents, m[k]) 28 | } 29 | } 30 | 31 | return g.findLongestSequence() 32 | } 33 | 34 | type Graph struct { 35 | parents []*Node 36 | } 37 | 38 | type Node struct { 39 | value int 40 | child *Node 41 | } 42 | 43 | func (g *Graph) findLongestSequence() int { 44 | max := math.MinInt64 45 | for _, p := range g.parents { 46 | counter := 1 47 | parent := p 48 | for parent.child != nil { 49 | counter++ 50 | parent = parent.child 51 | } 52 | if counter > max { 53 | max = counter 54 | } 55 | } 56 | return max 57 | } 58 | -------------------------------------------------------------------------------- /StringPermutation.go: -------------------------------------------------------------------------------- 1 | /* 2 | String permutations in Go 3 | This is an exercise in recursion encountered in programming training books: 4 | 5 | PROBLEM: Implement a routine that prints all possible orderings of the characters 6 | in a string. In other words, print all permutations that use all the characters from 7 | the original string. For example, given the string “hat”, your function should print 8 | the strings “tha”, “aht”, “tah”, “ath”, “hta”, and “hat”. Treat each character in the 9 | input string as a distinct character, even if it is repeated. Given the string “aaa”, 10 | your routine should print “aaa” six times. You may print the permutations in any 11 | order you choose. 12 | */ 13 | package main 14 | 15 | import "fmt" 16 | 17 | 18 | func startPermutation(input string) { 19 | p := &Permutation{ 20 | in: []rune(input), 21 | used: make([]bool, len(input)), 22 | } 23 | p.permute() 24 | } 25 | 26 | type Permutation struct { 27 | used []bool 28 | out []rune 29 | in []rune 30 | } 31 | 32 | func (p *Permutation) permute() { 33 | if len(p.out) == len(p.in) { 34 | fmt.Println(string(p.out)) 35 | return 36 | } 37 | 38 | for i := 0; i < len(p.in); i++ { 39 | if p.used[i] == true { 40 | continue 41 | } 42 | p.out = append(p.out, p.in[i]) 43 | p.used[i] = true 44 | p.permute() 45 | p.used[i] = false 46 | p.out = p.out[:len(p.out)-1] 47 | } 48 | } 49 | --------------------------------------------------------------------------------