diff --git a/README.md b/README.md index 7189779..c9bb8cf 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,8 @@ Blogs on Self-Hosting, Homelab and DevOps Technologies. - Rabin-Karp Substring Search - Checking an Array for Duplicate Values - Identifying Anagrams - - Finding Elements in an Array that Sum Up to a Target Value + - Finding Elements in an Array that Sum Up to a Target Value + - Group Anagrams in an Array ## Technologies Used - [Hugo Static Site Generator](https://gohugo.io/) diff --git a/config.yml b/config.yml index b1265ac..7f7ce03 100644 --- a/config.yml +++ b/config.yml @@ -30,9 +30,9 @@ languages: - name: Archive url: archives weight: 5 - # - name: Index - # url: https://github.com/bovem/bovem.github.io#index - # weight: 10 + - name: Index + url: contents + weight: 10 - name: Tags url: tags/ weight: 15 diff --git a/content/contents.md b/content/contents.md new file mode 100644 index 0000000..0c13808 --- /dev/null +++ b/content/contents.md @@ -0,0 +1,36 @@ +--- +title: "Index" +layout: "contents" +url: "/contents" +summary: "Index of all content" +--- + +- Kubernetes + - Containers + - Container Architecture + - Container Lifecycle + - Container Images + - Building Container Images + - Kubernetes Operators + - Operators on OpenShift + - Operator SDK and Bundle Images + - Helm Charts + - Container Network Interfaces (CNI) + - Container Storage Interfaces (CSI) + - Network Functions +- Homelab + - Building Your Own Homelab +- Go + - Go Programming Language + - File Handling in Go + - Concurrency in Go + - REST API Requests in Go +- Data Structures and Algorithms + - Time Complexity + - Arrays, Strings, and HashMaps + - Rabin-Karp Substring Search + - Checking an Array for Duplicate Values + - Identifying Anagrams + - Finding Elements in an Array that Sum Up to a Target Value + - Group Anagrams in an Array + diff --git a/content/posts/dsa/contains-duplicate/index.md b/content/posts/dsa/contains-duplicate/index.md index 8159bf1..83497ac 100644 --- a/content/posts/dsa/contains-duplicate/index.md +++ b/content/posts/dsa/contains-duplicate/index.md @@ -3,7 +3,7 @@ author: "Avnish" title: "Checking an Array for Duplicate Values" date: "2023-10-10" description: "Implementing a containsDuplicate function that returns true if there are duplicate elements present in the array and false otherwise" -tags: ["data-structures", "arrays", "hashmaps", "go", "neetcode-150"] +tags: ["data-structures", "arrays", "hashmaps", "go", "neetcode-150", "leetcode-easy"] categories: ["Data Structures"] series: ["Data Structures and Algorithms"] aliases: ["contains-duplicate"] diff --git a/content/posts/dsa/finding-elements-that-sum-up-to-target/index.md b/content/posts/dsa/finding-elements-that-sum-up-to-target/index.md index 14a2bde..d219d35 100644 --- a/content/posts/dsa/finding-elements-that-sum-up-to-target/index.md +++ b/content/posts/dsa/finding-elements-that-sum-up-to-target/index.md @@ -3,7 +3,7 @@ author: "Avnish" title: "Finding Elements in an Array that Sum Up to a Target Value" date: "2023-10-15" description: "Implementing a twoSums(inputArray, targetValue) function that returns the indices of two elements in inputArray which could be summed up to the targetValue" -tags: ["data-structures", "arrays", "hashmaps", "go", "neetcode-150"] +tags: ["data-structures", "arrays", "hashmaps", "go", "neetcode-150", "leetcode-easy"] categories: ["Data Structures"] series: ["Data Structures and Algorithms"] aliases: ["finding-elements-that-sum-up-to-target", "two-sums"] diff --git a/content/posts/dsa/group-anagrams-in-an-array/group-anagrams-brute-force-best.png b/content/posts/dsa/group-anagrams-in-an-array/group-anagrams-brute-force-best.png new file mode 100644 index 0000000..6b04367 Binary files /dev/null and b/content/posts/dsa/group-anagrams-in-an-array/group-anagrams-brute-force-best.png differ diff --git a/content/posts/dsa/group-anagrams-in-an-array/group-anagrams-brute-force-worst.png b/content/posts/dsa/group-anagrams-in-an-array/group-anagrams-brute-force-worst.png new file mode 100644 index 0000000..2da1132 Binary files /dev/null and b/content/posts/dsa/group-anagrams-in-an-array/group-anagrams-brute-force-worst.png differ diff --git a/content/posts/dsa/group-anagrams-in-an-array/group-anagrams-brute-force.png b/content/posts/dsa/group-anagrams-in-an-array/group-anagrams-brute-force.png new file mode 100644 index 0000000..69aae6b Binary files /dev/null and b/content/posts/dsa/group-anagrams-in-an-array/group-anagrams-brute-force.png differ diff --git a/content/posts/dsa/group-anagrams-in-an-array/group-anagrams-cover.png b/content/posts/dsa/group-anagrams-in-an-array/group-anagrams-cover.png new file mode 100644 index 0000000..3b3bd6d Binary files /dev/null and b/content/posts/dsa/group-anagrams-in-an-array/group-anagrams-cover.png differ diff --git a/content/posts/dsa/group-anagrams-in-an-array/group-anagrams-optimized.png b/content/posts/dsa/group-anagrams-in-an-array/group-anagrams-optimized.png new file mode 100644 index 0000000..93d19db Binary files /dev/null and b/content/posts/dsa/group-anagrams-in-an-array/group-anagrams-optimized.png differ diff --git a/content/posts/dsa/group-anagrams-in-an-array/group-anagrams-problem.png b/content/posts/dsa/group-anagrams-in-an-array/group-anagrams-problem.png new file mode 100644 index 0000000..43d684f Binary files /dev/null and b/content/posts/dsa/group-anagrams-in-an-array/group-anagrams-problem.png differ diff --git a/content/posts/dsa/group-anagrams-in-an-array/index.md b/content/posts/dsa/group-anagrams-in-an-array/index.md new file mode 100644 index 0000000..2c9e301 --- /dev/null +++ b/content/posts/dsa/group-anagrams-in-an-array/index.md @@ -0,0 +1,340 @@ +--- +author: "Avnish" +title: "Group Anagrams in an Array" +date: "2023-10-22" +description: "Implementing a groupAnagrams function that takes an array of strings as input and returns another array with anagrams grouped together" +tags: ["data-structures", "strings", "hashmaps", "go", "neetcode-150", "leetcode-medium"] +categories: ["Data Structures"] +series: ["Data Structures and Algorithms"] +aliases: ["group-anagrams-in-an-array", "group-anagrams"] +ShowToc: true +TocOpen: false +comments: false +cover: + image: "group-anagrams-cover.png" + linkFullImages: true + alt: "The groupAnagrams function will return an array with anagrams grouped together" + caption: "" + relative: false + responsiveImages: false +math: true +--- + +# Problem Statement +We have to implement a `groupAnagram` function that takes an array of strings as input and returns a new array with anagrams grouped. + +

Problem Statement for groupAnagrams

+ +The input string array is assumed to be composed entirely of lowercase English characters. + +# Brute Force Solution +If two strings are anagrams then their sorted order will be the same. Thus, anagrams could be grouped under their sorted order. + +

Brute Force solution for groupAnagrams

+ +The brute-force implementation of `groupAnagram` uses a hashmap for grouping. In this hashmap the sorted string will be the key and the original strings will be the values (stored in an array). At the end of the function, we can iterate over the hashmap and create an array of grouped anagrams. + +## Psuedo-code for the Brute Force Solution +```text +hashmap = HashMap() +loop index in stringArray + stringValue = stringArray[index] + sortedString = string(sort(stringValue)) + if hashmap[sortedString] + hashmap[sortedString].append(stringValue) + else + hashmap[sortedString] = [stringValue] + +returnedList = [] +loop key, value in hashmap + returnedList.append(value) + +return returnedList +``` + +## Best Case Scenario +The time taken to sort individual strings is assumed to be $O(k \log(k))$ (the time complexity of the best sorting algorithm) where $k$ is the size of the string. Since we have to perform this operation on every element the sorting operation will be repeated $n$ time, where $n$ is the size of the array, resulting in $O(n \times k \log(k))$ time. + +

Best case scenario for Brute Force solution for groupAnagrams

+ +The best-case input will contain just a single set of anagrams i.e. the hashmap will contain just one key. The loop over hashmap values will be executed only once. Thus, the total time complexity of grouping anagrams will be $O(n \times k \log(k))$. + +## Worst Case Scenario +

Worst case scenario for Brute Force solution for groupAnagrams

+ +The worst-case input array will contain zero anagrams and the hashmap will contain a key for each array element i.e. $n$ keys. Thus, the total time complexity of the function in the worst-case scenario will be $O(n + n \times k \log(k))$, which could be simplified to $O(n \times k \log(k))$. + +## Code for Brute Force Solution +```Go +package main + +import ( + "fmt" + "sort" + "strings" +) + +func sortString(inputString string)(string){ + listInputString := strings.Split(inputString, "") + sort.Strings(listInputString) + return strings.Join(listInputString, "") +} + +func groupAnagrams(inputArray []string)([][]string){ + hashmap := make(map[string][]string) + + // Loop over the inputArray and sort every string element + for index:=0;indexOptimized solution for groupAnagrams

+ +The `countHashMap` will be initialized with lowercase English characters (`a-z`) mapped to `0` (default count). The `load` function will iterate over the characters in the input string and increment their count, for example, `countHashMap.load("mat")` will increment the value of `m`, `a`, and `t` keys to `1`. + +As we have to use `countHashMap` as a key to another hashmap, we can simplify its data to a single string of non-zero count characters and their value, for example, `baseball => {a:2, b:2, c:0, d:0, e:1, ..., l:2, ..., s:1, ..., z:0} => a2b2e1l2s1` + +## Psuedo code for the Optimized Solution +```text +anagramHashmap = HashMap() +loop index in stringArray + countHashmap = HashMap[a-z, 0-0] + countHashmap.load(stringArray[index]) + + if anagramHashmap[countHashMap] + anagramHashmap[countHashMap].append(stringArray[index]) + else + anagramHashmap[countHashMap] = [stringArray[index]] + +returnedList = [] +for key, value in anagramHashmap + returnedList.append(value) + +return returnedList +``` + +## Best Case Scenario +The best-case input will contain only one set of anagrams. Thus the total time complexity of the function will be $O(n \times k)$. + +## Worst Case Scenario +For the worst-case input (none of the strings are anagrams) the loop over `anagramHashMap` will take $O(n)$ time. Hence, the time complexity of the function will be $O(n \times k)$ (generalized from $O(n + n \times k)$). + +## Code for Optimized Solution +First, we have to implement a `generateCountHashMap` function that will return a hashmap with keys ranging from `a` to `z` mapped to their initial count i.e. `0`. + +```Go +func generateCountHashMap()(map[string]int){ + countHashMap := make(map[string]int) + + // The time complexity of this function will + // be constant (O(1)) since the loop will + // execute only 26 times on every function call + for r:='a';r<='z';r++{ + countHashMap[string(r)] = 0 + } + return countHashMap +} +``` + +To simplify the presentation of data in `countHashMap` we have to convert it into an equivalent string using the `loadStringValue` function. + +```Go +func loadStringValue(countHashMap map[string]int, + inputString string)(string){ + + // Assuming the size of inputString is k + // the time complexity of executing this loop + // will be O(k) + for i:=0;i0{ + returnString = append(returnString, + string(r), + strconv.Itoa(countHashMap[string(r)])) + } + } + + return strings.Join(returnString, "") +} +``` + +Finally, we use `generateCountHashMap` and `loadStringValue` to implement the `groupAnagrams` function. + +```Go +func groupAnagrams(inputArray []string)([][]string){ + anagramHashMap := make(map[string][]string) + + for index:=0;index0{ + returnString = append(returnString, + string(r), + strconv.Itoa(countHashMap[string(r)])) + } + } + + return strings.Join(returnString, "") +} + +func groupAnagrams(inputArray []string)([][]string){ + anagramHashMap := make(map[string][]string) + + for index:=0;index + +Thank you for taking the time to read this blog post! If you found this content valuable and would like to stay updated with my latest posts consider subscribing to my RSS Feed. + +# Resources +49. Group Anagrams +Group Anagrams - Categorize Strings by Count - Leetcode 49 \ No newline at end of file diff --git a/content/posts/dsa/identifying-anagrams/index.md b/content/posts/dsa/identifying-anagrams/index.md index 098b485..f444ef2 100644 --- a/content/posts/dsa/identifying-anagrams/index.md +++ b/content/posts/dsa/identifying-anagrams/index.md @@ -2,8 +2,8 @@ author: "Avnish" title: "Identify Anagrams" date: "2023-10-12" -description: "Implementing an isAnagram() function that returns true if its two input strings are anagrams and false otherwise" -tags: ["data-structures", "strings", "hashmaps", "go", "neetcode-150"] +description: "Implementing an isAnagram function that returns true if its two input strings are anagrams and false otherwise" +tags: ["data-structures", "strings", "hashmaps", "go", "neetcode-150", "leetcode-easy"] categories: ["Data Structures"] series: ["Data Structures and Algorithms"] aliases: ["identifying-anagrams", "is-anagram"] diff --git a/themes/PaperMod b/themes/PaperMod index edf4632..1b4bc1d 160000 --- a/themes/PaperMod +++ b/themes/PaperMod @@ -1 +1 @@ -Subproject commit edf46324c40574e6000d55b20e3fe7ba1afd5412 +Subproject commit 1b4bc1d6defb8f38fb49f426e699a58858007fda