Skip to main content
deleted 42 characters in body
Source Link
rrowland
  • 440
  • 3
  • 9

My original assertion (Outdated):

Sorting a string (Or any array) is inefficient because even the fastest algorithm will sort no faster than O(n log n) in an average case. The most efficient way would use a hash map to count letters in each word. Something like:

Although reading from a hash map can be as quick as O(1), writing to a hash map is significantly slower. By using a 26-value array (0-25) to represent lowercase letters, the speed of operations can be sped up significantly:

function isAnagram(word1, word2) {
  if (!word1typeof ||word1 !word2== 'string' || !word1.lengthtypeof ||word2 !word2.length== 'string') {
    throw new Error('isAnagram requires two strings to be passed.')
  }

  var normalizedWord1 = word1.replace(/\s+[^A-Za-z]+/g, '').toLowerCase();
  var normalizedWord2 = word2.replace(/\s+[^A-Za-z]+/g, '').toLowerCase();

  var counts = [];
  var word1Length = normalizedWord1.length;
  var word2Length = normalizedWord2.length

  if (word1Length !== word2Length) { return false; }

  for (var i = 0; i < word1Length; i++) {
    var index = normalizedWord1.charCodeAt(i)-97;
    counts[index] = (counts[index] || 0) + 1;
  }

  for (var i = 0; i < word2Length; i++) {
    var index = normalizedWord2.charCodeAt(i)-97;
    if (!counts[index]) { return false; }
    else { counts[index]--; }
  }
 
  return counts.every(function(count) {
    return !count;
  });true;
}

EDIT: A speed comparison between using a hash and using a 26-value array: http://jsperf.com/anagram-algorithms

My original assertion (Outdated):

Sorting a string (Or any array) is inefficient because even the fastest algorithm will sort no faster than O(n log n) in an average case. The most efficient way would use a hash map to count letters in each word. Something like:

Although reading from a hash map can be as quick as O(1), writing to a hash map is significantly slower. By using a 26-value array (0-25) to represent lowercase letters, the speed of operations can be sped up significantly:

function isAnagram(word1, word2) {
  if (!word1 || !word2 || !word1.length || !word2.length) {
    throw new Error('isAnagram requires two strings to be passed.')
  }

  var normalizedWord1 = word1.replace(/\s+/g, '').toLowerCase();
  var normalizedWord2 = word2.replace(/\s+/g, '').toLowerCase();

  var counts = [];
  var word1Length = normalizedWord1.length;
  var word2Length = normalizedWord2.length

  if (word1Length !== word2Length) { return false; }

  for (var i = 0; i < word1Length; i++) {
    var index = normalizedWord1.charCodeAt(i)-97;
    counts[index] = (counts[index] || 0) + 1;
  }

  for (var i = 0; i < word2Length; i++) {
    var index = normalizedWord2.charCodeAt(i)-97;
    if (!counts[index]) { return false; }
    else { counts[index]--; }
  }
 
  return counts.every(function(count) {
    return !count;
  });
}

EDIT: A speed comparison between using a hash and using a 26-value array: http://jsperf.com/anagram-algorithms

My original assertion (Outdated):

Sorting a string (Or any array) is inefficient because even the fastest algorithm will sort no faster than O(n log n) in an average case. The most efficient way would use a hash map to count letters in each word. Something like:

Although reading from a hash map can be as quick as O(1), writing to a hash map is significantly slower. By using a 26-value array (0-25) to represent lowercase letters, the speed of operations can be sped up significantly:

function isAnagram(word1, word2) {
  if (typeof word1 !== 'string' || typeof word2 !== 'string') {
    throw new Error('isAnagram requires two strings to be passed.')
  }

  var normalizedWord1 = word1.replace(/[^A-Za-z]+/g, '').toLowerCase();
  var normalizedWord2 = word2.replace(/[^A-Za-z]+/g, '').toLowerCase();

  var counts = [];
  var word1Length = normalizedWord1.length;
  var word2Length = normalizedWord2.length

  if (word1Length !== word2Length) { return false; }

  for (var i = 0; i < word1Length; i++) {
    var index = normalizedWord1.charCodeAt(i)-97;
    counts[index] = (counts[index] || 0) + 1;
  }

  for (var i = 0; i < word2Length; i++) {
    var index = normalizedWord2.charCodeAt(i)-97;
    if (!counts[index]) { return false; }
    else { counts[index]--; }
  }

  return true;
}

EDIT: A speed comparison between using a hash and using a 26-value array: http://jsperf.com/anagram-algorithms

added 31 characters in body
Source Link
rrowland
  • 440
  • 3
  • 9

My original assertion (Outdated):

Sorting a string (Or any array) is inefficient because even the fastest algorithm will sort no faster than O(n log n) in an average case. The most efficient way would use a hash map to count letters in each word. Something like:

Although reading from a hash map can be as quick as O(1), writing to a hash map is significantly slower. By using a 26-value array (0-25) to represent lowercase letters, the speed of operations can be sped up significantly:

function isAnagram(word1, word2) {
  if (!word1 || !word2 || !word1.length || !word2.length) {
    throw new Error('isAnagram requires two strings to be passed.')
  }

  var normalizedWord1 = word1.replace(/\s+/g, '').toLowerCase();
  var normalizedWord2 = word2.replace(/\s+/g, '').toLowerCase();

  var counts = [];
  var word1Length = normalizedWord1.length;
  var word2Length = normalizedWord2.length

  if (word1Length !== word2Length) { return false; }

  for (var i = 0; i < word1Length; i++) {
    var index = normalizedWord1.charCodeAt(i)-97;
    counts[index] = (counts[index] || 0) + 1;
  }

  for (var i = 0; i < word2Length; i++) {
    var index = normalizedWord2.charCodeAt(i)-97;
    counts[index] =if (!counts[index]) ||{ 0)return false; }
    else { counts[index]--; 1;}
  }

  return counts.every(function(count) {
    return !count;
  });
}

EDIT: A speed comparison between using a hash and using a 26-value array: http://jsperf.com/anagram-algorithms

My original assertion (Outdated):

Sorting a string (Or any array) is inefficient because even the fastest algorithm will sort no faster than O(n log n) in an average case. The most efficient way would use a hash map to count letters in each word. Something like:

Although reading from a hash map can be as quick as O(1), writing to a hash map is significantly slower. By using a 26-value array (0-25) to represent lowercase letters, the speed of operations can be sped up significantly:

function isAnagram(word1, word2) {
  if (!word1 || !word2 || !word1.length || !word2.length) {
    throw new Error('isAnagram requires two strings to be passed.')
  }

  var normalizedWord1 = word1.replace(/\s+/g, '').toLowerCase();
  var normalizedWord2 = word2.replace(/\s+/g, '').toLowerCase();

  var counts = [];
  var word1Length = normalizedWord1.length;
  var word2Length = normalizedWord2.length

  if (word1Length !== word2Length) { return false; }

  for (var i = 0; i < word1Length; i++) {
    var index = normalizedWord1.charCodeAt(i)-97;
    counts[index] = (counts[index] || 0) + 1;
  }

  for (var i = 0; i < word2Length; i++) {
    var index = normalizedWord2.charCodeAt(i)-97;
    counts[index] = (counts[index] || 0) - 1;
  }

  return counts.every(function(count) {
    return !count;
  });
}

EDIT: A speed comparison between using a hash and using a 26-value array: http://jsperf.com/anagram-algorithms

My original assertion (Outdated):

Sorting a string (Or any array) is inefficient because even the fastest algorithm will sort no faster than O(n log n) in an average case. The most efficient way would use a hash map to count letters in each word. Something like:

Although reading from a hash map can be as quick as O(1), writing to a hash map is significantly slower. By using a 26-value array (0-25) to represent lowercase letters, the speed of operations can be sped up significantly:

function isAnagram(word1, word2) {
  if (!word1 || !word2 || !word1.length || !word2.length) {
    throw new Error('isAnagram requires two strings to be passed.')
  }

  var normalizedWord1 = word1.replace(/\s+/g, '').toLowerCase();
  var normalizedWord2 = word2.replace(/\s+/g, '').toLowerCase();

  var counts = [];
  var word1Length = normalizedWord1.length;
  var word2Length = normalizedWord2.length

  if (word1Length !== word2Length) { return false; }

  for (var i = 0; i < word1Length; i++) {
    var index = normalizedWord1.charCodeAt(i)-97;
    counts[index] = (counts[index] || 0) + 1;
  }

  for (var i = 0; i < word2Length; i++) {
    var index = normalizedWord2.charCodeAt(i)-97;
    if (!counts[index]) { return false; }
    else { counts[index]--; }
  }

  return counts.every(function(count) {
    return !count;
  });
}

EDIT: A speed comparison between using a hash and using a 26-value array: http://jsperf.com/anagram-algorithms

Post Migrated Here from stackoverflow.com (revisions)
Source Link
rrowland
  • 440
  • 3
  • 9

My original assertion (Outdated):

Sorting a string (Or any array) is inefficient because even the fastest algorithm will sort no faster than O(n log n) in an average case. The most efficient way would use a hash map to count letters in each word. Something like:

Although reading from a hash map can be as quick as O(1), writing to a hash map is significantly slower. By using a 26-value array (0-25) to represent lowercase letters, the speed of operations can be sped up significantly:

function isAnagram(word1, word2) {
  if (!word1 || !word2 || !word1.length || !word2.length) {
    throw new Error('isAnagram requires two strings to be passed.')
  }

  var normalizedWord1 = word1.replace(/\s+/g, '').toLowerCase();
  var normalizedWord2 = word2.replace(/\s+/g, '').toLowerCase();

  var counts = [];
  var word1Length = normalizedWord1.length;
  var word2Length = normalizedWord2.length

  if (word1Length !== word2Length) { return false; }

  for (var i = 0; i < word1Length; i++) {
    var index = normalizedWord1.charCodeAt(i)-97;
    counts[index] = (counts[index] || 0) + 1;
  }

  for (var i = 0; i < word2Length; i++) {
    var index = normalizedWord2.charCodeAt(i)-97;
    counts[index] = (counts[index] || 0) - 1;
  }

  return counts.every(function(count) {
    return !count;
  });
}

EDIT: A speed comparison between using a hash and using a 26-value array: http://jsperf.com/anagram-algorithms