0

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;
};
YakovL
  • 7,557
  • 12
  • 62
  • 102
JaneJin
  • 5
  • 1
  • 3

6 Answers6

2

This is my version of solution. You can even skip join() at the end of, since you still can compare two arrays.

const isAnagram = function(s, t) {
  if (s.length !== t.length ) {
    return false;
    }
  if (s.split('').sort().join('') === t.split('').sort().join('')) {
    return true;
  } else {
    return false;
  }
};
Asylbek
  • 31
  • 2
0

++ is the increment operator. It can be pre-fixed (++i) or post-fixed (i++). In this case it is post-fixed: result1[s.charCodeAt(i) - 97]++, so it will increment the value of result1[s.charCodeAt(i) - 97].

26 is simply the number of letters in the alphabet (from a to z).

The code is initializing the two arrays and filling them with 0s so that it can use the array elements as counters. Each index in the array represents a letter in the alphabet, and stores the occurrences of that letter in the string.

Thiago Barcala
  • 6,463
  • 2
  • 20
  • 23
0

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.

YakovL
  • 7,557
  • 12
  • 62
  • 102
0

With minimum array functions and single for loop

    function anagram(str1, str2){
        var isAnagram = true;
        if(str1.length != str2.length){
            isAnagram = false;
        }else{
            for(var i=0; i<str1.length;i++) {       
                if(!str2.includes(str1[i])){
                    isAnagram = false;
                }   
            }
        }

        if(isAnagram){
            console.log('string is anagram');
        }else{
            console.log('string is not anagram');
        }
    }

    anagram('READ', 'DEAR');
glinda93
  • 7,659
  • 5
  • 40
  • 78
Rhl singh
  • 88
  • 1
  • 3
0
var isAnagram = function(s, t) {
  let sArr = s.split('');
  let tArr = t.split('');

  sArr.sort();
  let newS = sArr.join('');

  tArr.sort();
  let newT = tArr.join('');

  return newS === newT; 
};
Akhil Gupta
  • 43
  • 1
  • 8
0

this can be done with only one line of code

const isAnagram = (s,t) => ( [...s].sort().join('') === [...t].sort().join(''))

console.log( isAnagram('anagram', 'nagaram') )  // true
console.log( isAnagram('anagram', 'xxx') )     // false

But your question also asks to manage all the utf8 characters, which I interpret as having to eliminate the diacritic, for which there is an answer here.

that I changed a little to keep only the letters (which excludes spaces and other punctuation), to be able to process anagrams of several words too :

const letters = str => str.toLowerCase().normalize("NFD").replace(/[^a-z]/g, '')

which has for final solution:

const letters = str => str.toLowerCase().normalize("NFD").replace(/[^a-z]/g, '')
  ,   isAnagram = (s,t) => ( [...letters(s)].sort().join('') === [...letters(t)].sort().join(''))
  ;
const anagrams =  // from wikipedia
  [ { s: "evil"
    , t: "vile"                     }
  , { s: "New York Times"
    , t: "monkeys write"            }
  , { s: "William Shakespeare"
    , t: "I am a weakish speller"   }
  , { s: "Le commandant Cousteau"
    , t: "Tout commença dans l'eau" }  // with diacritic ( French )
  , { s: "La crise économique"
    , t: "Le scénario comique"      }
  , { s: "Question sans réponse"
    , t: "Enquêtons sans espoir"    }
  , { s: "Chauve-souris"
    , t: "Souche à virus"           }
  ]

for (let {s,t} of anagrams )
    console.log(`_${s}_, _${t}_ -> `, isAnagram(s,t))
.as-console-wrapper { max-height: 100% !important; top: 0; }
Mister Jojo
  • 20,093
  • 6
  • 21
  • 40