sherlock 例程
This post is going to get you through my solution to a coding challenge called “Sherlock and Anagrams.” You may take a look at it in HackerRank.
这篇文章将帮助您解决称为“ Sherlock and Anagrams”的编码挑战。 您可以在HackerRank中查看它。
I spent a lot of time trying to solve it, with JavaScript. When I tried to google it, I could not find a decent JS solution. I found just one, and it was not working correctly. Also, any explanations were completely out of the question. That’s why I decided to write an article about it and try to put some nice and easy to digest explanations along the way. Keep reading now!
我花了很多时间尝试用JavaScript解决它。 当我尝试使用Google进行搜索时,找不到合适的JS解决方案。 我发现只有一个,但无法正常工作。 另外,任何解释都是完全不可能的。 这就是为什么我决定写一篇有关它的文章,并尝试在此过程中提出一些易于理解的解释的原因。 现在继续阅读!
⚠️CAUTION: I will roll out my solution below with short explanations about each of the steps. If you want to give a try yourself, please stop here and go to HackerRank’s site.
⚠️注意: 我将在下面推出我的解决方案,并简要说明每个步骤。 如果您想尝试一下,请在此处停止并访问HackerRank的网站。
问题 (Problem)
Two strings are anagrams of each other if the letters of one string can be rearranged to form the other string. Given a string, find the number of pairs of substrings of the string that are anagrams of each other.
如果可以重新排列一个字符串的字母以形成另一个字符串,则两个字符串彼此是字谜 。 给定一个字符串,找到该字符串的子字母对之间的数目。
For example s = mom, the list of all anagrammatic pairs is [m, m], [mo, om] at positions [[0], [2]], [[0, 1], [1, 2]] respectively.
例如s = mom ,所有字母对的列表分别在[[0],[2]],[[0、1],[1、2]]的位置上是[ m,m ],[ mo,om ] 。
ConstraintsLength of the input string: 2 ≤ |s| ≤ 100String s contains only lowercase letters from the range ascii[a-z].
约束输入字符串的长度:2≤| s | ≤100String s仅包含ascii [az]范围内的小写字母。
分析 (Analysis)
First thing first — we need to get a better understanding of the whole problem. What is an anagram? What is an anagrammatic pair? Can I see one? Also, what exactly does it mean substrings?
首先,我们需要对整个问题有更好的了解。 什么是字谜? 什么是字谜对? 我可以看到一个吗? 另外, 子字符串到底是什么意思?
In other words, we need to have a clear picture of what are we trying to solve, before solving it.
换句话说,在解决之前,我们需要清楚地了解我们要解决的问题。
From the description of the problem, we can deduct all we need. Keep walking! ?
从问题的描述中,我们可以扣除所有需要的信息。 继续走! ?
I think this is a good moment to mention that the challenge in question is under the “Dictionaries and Hashmaps” section in the HackerRank website. You’ll probably think that you should use this kind of data structure when solving it. ?
我认为现在是提提这个问题的好时机,有关的挑战是在HackerRank网站的“词典和哈希图”部分下。 您可能会认为在解决它时应该使用这种数据结构。 ?
字谜 (Anagrams)
Since we are going to look for anagrams, let’s start with them. As it is described above, an anagram of one word is another word that has the same length and is created with the same characters from the former word.
由于我们要查找字谜,因此我们从它们开始。 如上所述,一个单词的字谜是另一个单词,其长度相同,并且是由与前一个单词相同的字符创建的。
So we will have to look for words and compare them with other words, in order to see if they are anagrammatic pairs. Once found, we will just count them.
因此,我们将不得不寻找单词并将它们与其他单词进行比较,以查看它们是否是字词对。 一旦找到,我们将只计算它们。
语法对 (Anagrammatic pairs)
Since we’ve seen what an anagram is, it should be relatively easy to conclude that an anagrammatic pair is just two strings that are anagrams. Such as “mo” and “om”, or “listen” and “silent”. We will have to count how many pairs like this can be found in a given string. In order to do that, we need to split this original string to substrings.
既然我们已经看过什么是字谜,那么应该容易地得出一个结论,即一个字谜对只是两个作为字谜的字符串。 例如“ mo”和“ om”,或“ listen”和“ silent”。 我们将必须计算在给定的字符串中可以找到多少对这样的对。 为此,我们需要将此原始字符串拆分为子字符串。
子串 (Substrings)
Substrings, as the name infers, are parts of a string. These parts could be just a letter or a pair of letters, such as what have we seen in the example above — “m” or “mo.” In our solution, we will split the original string to such substrings and then we will go over them and do the comparison, which will tell us whether we have anagrammatic pairs among them.
顾名思义,子字符串是字符串的一部分。 这些部分可能只是一个字母或一对字母,例如在上面的示例中看到的“ m ”或“ mo”。 在我们的解决方案中,我们将原始字符串拆分成这样的子字符串,然后遍历它们并进行比较,这将告诉我们是否在它们之间存在语法对。
解 (Solution)
Now that we’ve done our analysis, it’s showtime! ?
现在我们已经完成了分析,现在是放映时间! ?
Let’s summarize:
让我们总结一下:
- We need to find all substrings of the given string — create a method for that. 我们需要找到给定字符串的所有子字符串-为此创建一个方法。
- We need to be able to check if two strings are anagrams — create a method for that. 我们需要能够检查两个字符串是否为字谜-为此创建一个方法。
- We need to count all anagrammatic pairs in the given string — create a method for that. 我们需要计算给定字符串中的所有语法符号对-为此创建一个方法。
- Combine everything from above and spit the result — create a method for that. 从上面组合所有内容并吐出结果-为此创建一个方法。
获取所有子字符串 (Get all substrings)
This will be our helper method for finding all substrings of a given string:
这将是我们的帮助方法,用于查找给定字符串的所有子字符串:
function getAllSubstrings(str) {
let i, j, result = [];
for (i = 0; i < str.length; i++) {
for (j = i + 1; j < str.length + 1; j++) {
result.push(str.slice(i, j))
}
}
return result
}
As you can see, it has O(n²) time complexity. For our case, it does the job, because we have limited length of the input string (up to 100 characters).
如您所见,它具有O(n²)时间复杂度。 对于我们的情况,它可以完成工作,因为输入字符串的长度有限(最多100个字符)。
检查字谜 (Check for anagrams)
This will be our helper method for checking if two strings are anagrammatic pairs:
这将是我们的辅助方法,用于检查两个字符串是否为语法对:
function isAnagram(str1, str2) {
const hist = {}
for (let i = 0; i < str1.length; i++) {
const char = str1[i]
if (hist[char]) {
hist[char]++
} else {
hist[char] = 1
}
}
for (let j = 0; j < str2.length; j++) {
const char = str2[j]
if (hist[char]) {
hist[char]--
} else {
return false
}
}
return true
}
Remember that we assumed we’d most probably have to use data structures such as hashmaps or dictionaries (given the section where this challenge is found on HackerRank).
请记住,我们假设我们极有可能必须使用诸如哈希图或字典之类的数据结构(鉴于在HackerRank上发现此挑战的部分)。
We use a simple JavaScript object to play the role of a hashmap. We do two iterations — one per string. When we iterate over the first one, we add its characters as keys to the hashmap and count their appearances, which are going to be stored as their values. Then we do another iteration over the second string. Check if its characters are stored in our hashmap. If yes — decrement their value. If there are missing characters, which means the two strings are not an anagrammatic pair, we simply return false. If both loops complete, we return true, signifying that the strings being analyzed are an anagrammatic pair.
我们使用一个简单JavaScript对象来扮演哈希图的角色。 我们进行两次迭代-每个字符串一次。 当我们遍历第一个时,我们将其字符作为键添加到哈希图中,并计算其外观,这些外观将作为其值存储。 然后,对第二个字符串进行另一个迭代。 检查其字符是否存储在我们的哈希图中。 如果是,请降低其价值。 如果缺少字符,这意味着两个字符串不是一个语法符号对,我们只返回false。 如果两个循环都完成,则返回true,表示正在分析的字符串是一个语法符号对。
进行计数 (Do the counting)
This is the method, where we will use the helper for checking if a pair is anagrammatic and count it. We do that with the help of JavaScript arrays and the methods they provide. We iterate over an array containing all the substrings of the original string. Then we get the correct element and remove it from the array. And then we do another loop through that array and return 1 if we find that there is an anagram of the current element. If nothing is found, we return 0.
这是一种方法,在此方法中,我们将使用帮助程序来检查一对是否有语法符号并对其进行计数。 我们借助JavaScript数组及其提供的方法来做到这一点。 我们遍历包含原始字符串的所有子字符串的数组。 然后,我们获得正确的元素并将其从数组中删除。 然后,我们对该数组进行另一个循环,如果发现当前元素有一个字谜,则返回1。 如果未找到任何内容,则返回0。
function countAnagrams(currentIndex, arr) {
const currentElement = arr[currentIndex]
const arrRest = arr.slice(currentIndex + 1)
let counter = 0
for (let i = 0; i < arrRest.length; i++) {
if (currentElement.length === arrRest[i].length && isAnagram(currentElement, arrRest[i])) {
counter++
}
}
return counter
}
最后 (And in the end)
The only thing left to be done now is to combine all of the above and spit the desired result. Here is how the final method looks like:
现在剩下要做的唯一一件事就是结合以上所有内容并吐出所需的结果。 最终方法如下所示:
function sherlockAndAnagrams(s) {
const duplicatesCount = s.split('').filter((v, i) => s.indexOf(v) !== i).length
if (!duplicatesCount) return 0
let anagramsCount = 0
const arr = getAllSubstrings(s)
for (let i = 0; i < arr.length; i++) {
anagramsCount += countAnagrams(i, arr)
}
return anagramsCount
}
Maybe you have noticed, here I am checking first for duplicates in order to know if I should continue further. As if there are no duplicated letters, then it’s not possible to have an anagram.
也许您已经注意到,在这里我首先检查重复项,以便知道是否应该继续。 仿佛没有重复的字母,就不可能有一个字谜。
And finally, we get all substrings into an array, iterate over it, count the anagrammatic pairs that are found and return this number.
最后,我们将所有子字符串放入数组中,对其进行迭代,计算找到的语法对,然后返回该数字。
You can find the full code here.
您可以在此处找到完整的代码。
结论 (Conclusion)
These kind of exercises are very good for making you think algorithmically. Also they change your way of working in your day to day job. My recommendation would be to do the same I am trying to do — train your brain now and then with one of those. And if you can — share. I know sometimes you don’t have time for such challenges, but when you do — go for it.
这些练习非常有助于您从算法上进行思考。 此外,它们还会改变您的日常工作方式。 我的建议是做我尝试做的相同事情–时不时地训练其中之一。 如果可以,请分享。 我知道有时候您没有时间面对这样的挑战,但是当您遇到挑战时,那就去吧。
My personal feeling after finishing this was total satisfaction, which is completely understandable, considering the time it took me to do it. But in the end, dear reader, I am even happier I can share this experience with you?!
考虑到我花的时间,我个人的感觉是完全满意,这完全可以理解。 但是最后,亲爱的读者,我更开心可以与您分享这种经验了!
Thanks for reading. Read more of my articles at mihail-gaberov.eu.
谢谢阅读。 在mihail-gaberov.eu上阅读我的更多文章。
sherlock 例程