Search code examples
javascriptanagram

understanding solution of Valid Anagram in javascript


This is from LeetCode - Valid Anagram

Given two strings s and t , write a function to determine if t is an anagram of s.
Example 1:
Input: s = "anagram", t = "nagaram"
Output: true
Example 2:

You may assume the string contains only lowercase alphabets.

Follow up: What if the inputs contain unicode characters? How would you adapt your solution to such case?

I don't understand these code below

  • result1[s.charCodeAt(i) - 97]++; --> what does ++ mean?
  • result2.length = 26; --> what does 26 stand for?
  • result2.fill(0); --> why does fill it with 0?

Please advise!

var isAnagram = function(s,t) {
    if (s.length !== t.length)
        result false;
    const result1 = [];
    result1.length = 26;
    result1.fill(0);

    const result2 = [];
    result2.length = 26;
    result2.fill(0);

    for (let i = 0; i < s.length; i++) {
        result1[s.charCodeAt(i) - 97]++;
        result2[t.charCodeAt(i) - 97]++;
    }

    for (let i = 0; i < result1.length; i++) {
        if (result1[i] !== result2[i]) {
            return false;
        }
    }
    return true;
};

Solution

  • That's somewhat poorly written code, let's improve it a bit so that your question are automatically gone:

    var isAnagram = function(string1, string2) {
        if (string1.length !== string2.length)
            return false; // here was a typo: result false
    
        const alphabetLength = 26;
        // returns an array of zeros (empty counters), each one per alphabet letter
        const getAlphabetCounters = function() {
            const counters = [];
            counters.length = alphabetLength;
            counters.fill(0);
            return counters;
        }
        const countCharacter = function(c, counters) {
            // zero for a, 25 for z
            const position = c.charCodeAt(0) - 97;
            counters[position]++;
        }
    
        const counters1 = getAlphabetCounters();
        const counters2 = getAlphabetCounters();
    
        for (let i = 0; i < string1.length; i++) {
            countCharacter(string1[i], counters1);
            countCharacter(string2[i], counters2);
        }
    
        for (let i = 0; i < counters1.length; i++) {
            if (counters1[i] !== counters2[i]) {
                return false;
            }
        }
        return true;
    };
    

    But it would be probably a better idea to use a "decremental" approach like this:

    var isAnagram = function(string1, string2) {
        if (string1.length !== string2.length)
            return false;
    
        let letters1 = string1.split('');
        let letters2 = string2.split('');
        for (let letter of letters1) {
            let position = letters2.indexOf(letter);
            if(position == -1)
                return false;
            letters2.splice(position, 1);
        }
        return true;
    };
    

    or if one cares about performance for long strings, sorting letters in those and direct comparison would be the way to go.