Confused regarding time complexity of different implementations (Hash map setting/getting slower than N-loop)

Viewed 33

I am having some trouble understanding a pattern I am seeing with a leet code problem I have been doing. The question regards detecting the longest palindrome in a string. I figured using a hashmap to determine palindromes, where length 1= palindrome, length 2 where characters are the same is a palindrome, and where if the first and last characters, and all the characters in the middle is a palindrome (detected by hash map) Basically this implementation with a hash map should be able to detect if something is a palindrome of 0(1) time complexity. But its much slower than the implementation without a hashmap, where we use a for loop to detect if a substring is a palindrome in 0(n): Here are the two imeplementations, does anyone know why the first is so much slower than the second. Shouldn't it be much quicker?

Slow implementation

/**
 * @param {string} s
 * @return {string}
 */
var longestPalindrome = function (s) {
  let palindromes = new Map();
  let palin = s[0];
  for (let c = 0; c <= s.length; c++) {
    for (let r = 0; r < c; r++) {
      let tempStr = s.slice(r, c);
      if (tempStr.length == 1) {
        palin = tempStr.length > palin.length ? tempStr : palin;
        palindromes.set(r + "r" + c + "c", true);
      } else if (tempStr.length == 2) {
        if (tempStr[0] === tempStr[1]) {
          palin = tempStr.length > palin.length ? tempStr : palin;
          palindromes.set(r + "r" + c + "c", true);
        }
      } else if (tempStr[0] === tempStr[tempStr.length - 1]) {
        if (palindromes.get(r + 1 + "r" + (c - 1) + "c") === true) {
          palin = tempStr.length > palin.length ? tempStr : palin;
          palindromes.set(r + "r" + c + "c", true);
        }
      } else {
        palindromes.set(r + "r" + c + "c", false);
      }
    }
  }
  return palin;

};

Faster implementation, for some reason

var isPalidrome = function (s) {
  for (var i = 0; i < s.length / 2; i++) {
    if (s[i] !== s[s.length - i - 1]) {
      return false;
    }
  }
  return true;
};
var longestPalindrome = function (s) {
  let palindromes = new Map();
  var max = s[0];
  let palin = "";
  for (let c = 0; c <= s.length; c++) {
    for (let r = 0; r < c; r++) {
      let tempStr = s.slice(r, c);
      if (isPalidrome(tempStr)) {
        max = tempStr.length > max.length ? tempStr : max;
      }
    }
  }
  return max;
};

Thanks!

EDIT: So by allocating and using array indices instead of the map, I made it finally run quicker than the N loop implementation. I guess my question is, why isn't the Map accesses 0(1). Is Javascript not using the most efficient map implementation or something? Do maps get very slow where their big for some reason? Some help understanding this would be appreciated.

So to Refactor my question: Why is this:

/**
 * @param {string} s
 * @return {string}
 */
var longestPalindrome = function (s) {
  let palindromes2 = [];
  for (let i = 0; i < s.length; i++) {
    palindromes2.push([]);
  }
  let palin = s[0];
  for (let c = 0; c <= s.length; c++) {
    for (let r = 0; r < c; r++) {
      let tempStr = s.slice(r, c);

      if (tempStr.length == 1) {
        palin = tempStr.length > palin.length ? tempStr : palin;
        palindromes2[r][c] = true;
      } else if (tempStr.length == 2) {
        if (tempStr[0] === tempStr[1]) {
          palin = tempStr.length > palin.length ? tempStr : palin;
          palindromes2[r][c] = true;
        } else {
          palindromes2[r][c] = false;
        }
      } else if (tempStr[0] === tempStr[tempStr.length - 1]) {
        if (palindromes2[r + 1][c - 1] === true) {
          palin = tempStr.length > palin.length ? tempStr : palin;
          palindromes2[r][c] = true;
        } else {
          palindromes2[r][c] = false;
        }
      } else {
        palindromes2[r][c] = false;
      }
    }
  }
  return palin;
};

SOOOO much faster (6x+ faster) than the first implementation I posted, with a hash map.

Thanks.

0 Answers
Related