Skip to main content
43 events
when toggle format what by license comment
Aug 10, 2015 at 4:43 comment added JcT Glad to help! Regarding performance, this code now performs pretty well against the prime hashing technique when you test against values that aren't anagrams; which, to be fair, most aren't. There is a potential speed improvement if you set counts to an array with 26 zeros (you can remove the || in the first loop, and I think some engines can optimise better knowing the length and type in the array), but it does make the code a little less pretty: jsperf.com/anagram-algorithms/7
Aug 10, 2015 at 3:52 comment added rrowland All good points @JcT, I've updated the answer.
Aug 10, 2015 at 3:52 history edited rrowland CC BY-SA 3.0
deleted 42 characters in body
Aug 10, 2015 at 1:24 comment added JcT Any thoughts as to whether you could also get away with typeof word1 !== "string" || typeof word2 !== "string" in the guard at the top of the function? Guarantees we're not receiving an Array; one empty string will fail the length check, two will pass on through as anagrams. I suppose "" is in fact an anagram of ""!
Aug 10, 2015 at 1:08 comment added JcT One other consideration - the regex we're using to strip spaces doesn't necessarily guarantee we only have alphas left; but our expectation of having a 26-value array assumes we are; I'd think there'd be some potential issues there.
Aug 10, 2015 at 1:05 comment added JcT Ah, but we know they're both the same length - so we'll either have exactly the same letters in the second string, or we'll have a letter in it that we don't have in the first. The first word having more of something means it will also have less of something else, since both words have the same available space. So say we had abb and abc (where the first has more 'b's than the first); in the second loop, we'll fail when we try to subtract from c, yes? If we survive the second loop, it means we had the same lengths and the second word didn't have any chars that weren't in the first.
Aug 10, 2015 at 0:11 comment added rrowland @JcT The .every loop is still catching instances where the first word has more of a certain letter than the second. The conditional is only catching instances where the second word has more of a certain letter than the first.
Aug 9, 2015 at 23:59 comment added JcT Just a thought - now that the conditional is in there, you may not even need that last .every loop. Anything I'm missing in thinking you can just return true?
Aug 8, 2015 at 19:48 comment added Winston Ewert @Aron, HashMap aren't implemented using heaps, you have no idea what you are talking about. See for example the wikipedia article which describes the array of buckets, and never mentions heaps. The fact is, using a heap to implement a hash map is utterly nonsensical.
Aug 7, 2015 at 18:21 comment added Simon Kuang I think my solution might be a little bit faster.
Aug 7, 2015 at 15:19 comment added rrowland @JcT Great observation! I've added a conditional.
Aug 7, 2015 at 15:18 history edited rrowland CC BY-SA 3.0
added 31 characters in body
Aug 7, 2015 at 14:51 comment added JcT You may be able to return false from that second loop a bit earlier (before attempting to subtract) if !counts[index].
Aug 7, 2015 at 9:25 comment added Ismael Miguel if (!word1 || !word2 || !word1.length || !word2.length) will fail if I pass an array or an array-like object.
Aug 7, 2015 at 8:48 history migrated from stackoverflow.com (revisions)
Aug 7, 2015 at 7:14 comment added rrowland Check out the speed delta! jsperf.com/anagram-algorithms
Aug 7, 2015 at 7:12 comment added rrowland @Aron You made a good point about insertion speed. I sped up the algorithm by converting the lowercase characters to values 0-25 so they can quickly be looked up in by array index rather than by hash key.
Aug 7, 2015 at 7:02 comment added Aron @Bergi As you fill in the Bucket Heap, it tends to an array.
Aug 7, 2015 at 7:01 comment added rrowland @jpmc26 You're right, it was broken. But, the problem was I forgot to initialize the letters in the hash as Numbers. So I was trying to ++ on undefined and they all became NaN which made them equal. The updated code is working again.
Aug 7, 2015 at 6:58 comment added Bergi @Aron: What do you mean by "at the size we are working in"? If we put a bound on input size (word length), we get O(1), and if we put a bound on the number of characters we get O(n) (linear to input size).
Aug 7, 2015 at 6:57 comment added jpmc26 @Bergi Whoops. I misdiagnosed the cause. Thanks. =)
Aug 7, 2015 at 6:54 comment added Aron @Bergi no I am not. At the size we are working in, it is n log n. The log n part however is bounded...
Aug 7, 2015 at 6:53 comment added Bergi @Aron: I think you're confusing a heap with the heap. Yes, initialising the map with the 26 expected letters might improve the performance, but that's really not needed as JS objects dynamically resize their maps.
Aug 7, 2015 at 6:48 comment added Bergi @jpmc26 has a point here. You forgot to initialise your properties, and they all are becoming NaN (which is falsy in the end, you might better have used an explicit == 0).
Aug 7, 2015 at 6:48 comment added Aron @Bergi The buckets are typically stored in a Heap. You could create an implementation based on an constant sized array (which would need to be the size of 2^(size of the hash). But that is typically quite memory inefficient. In this case, we KNOW that there are only 26 different chars (excluding accents (yes english HAS accents you naïve fool)) and you can base an algorithm on an array sized 26, but it wouldn't be a generic HashMap. In fact it would not be a HashMap, since the identity function can hardly be called a Hash function.
Aug 7, 2015 at 6:44 comment added Bergi @Aron: Some indexed constant access structue, call it array of buffer or whatever.
Aug 7, 2015 at 6:43 comment added Aron @Bergi Where are the buckets stored?
Aug 7, 2015 at 6:42 comment added jpmc26 This function is broken. isAnagram('abccd', 'abcdd') gives back true. You need to make sure the count of each letter is the same in both hashes, not just that they have the same set of distinct letters.
Aug 7, 2015 at 6:41 comment added Bergi @Aron: Where did you get that from? A HashMap is implemented using hashing, with amortised O(1) access. No heapsort going on.
Aug 7, 2015 at 6:37 comment added Aron -1 Because a HashMap is typically implemented as a Heap, which is O(log n) for inserting. More to the point. You are in effect doing the equivilent of an Insert Sort on a Heap, which "dun dun dun" is O(n log n).
Aug 7, 2015 at 6:04 comment added Bergi You should consider using every instead of reduce.
Aug 7, 2015 at 5:08 comment added rrowland @EasyBB Yeah I wasn't aware for..in was that much slower. A quick Google search enlightened me. Thanks!
Aug 7, 2015 at 4:53 comment added Tushar @rrowland Anyway !word1 || !word2 || !word1.length || !word2.length is redundant. You can remove one of them.
Aug 7, 2015 at 4:50 comment added rrowland @Tushar +1 on removing trim and using \s. 0 is not a string. "0" is truthy.
Aug 7, 2015 at 4:48 comment added Tushar @rrowland Also remove !word1 || !word2 || . Will not work if I passed 0 as one of the string
Aug 7, 2015 at 4:45 comment added Tushar @rrowland You can remove trim() from word1.trim().replace(/ /g, ''); As replace is removing spaces. Also, use \s+ instead of space ` ` in regex
Aug 7, 2015 at 4:27 comment added Tushar @ItaloAyres See Anagram Wiki. Notice William Shakespeare = I am a weakish speller. This answer will state that these are not Anagrams
Aug 7, 2015 at 4:27 comment added Italo Ayres @rrowland I just mentally jumped the use of sort() method. Thanks! And about the "which is the fastest" discussion, I prefer solving it the easy way: testing it! haha.
Aug 7, 2015 at 4:23 comment added rrowland @ItaloAyres Both other solutions are sorting the letters of the word alphabetically and comparing. That will check for anagrams. The difference between our approaches is the computational complexity of the algorithms.
Aug 7, 2015 at 4:19 comment added Italo Ayres I don't get it. The OP and @Tushar solution only check if the word is a palindrome, am I wrong? I so, this is the only correct solution by now, because checks anagrams.
Aug 7, 2015 at 4:17 comment added rrowland @Tushar If you're interested in learning a little about computational complexity: en.wikipedia.org/wiki/Big_O_notation
Aug 7, 2015 at 4:13 comment added rrowland Yes. 3n is an order of magnitude faster than n log n.
Aug 7, 2015 at 3:50 history answered rrowland CC BY-SA 3.0