Course Content
Understanding Algorithmic Complexity
In the module, we discuss the existence of multiple algorithms to solve a single problem. The challenge lies in determining the most efficient algorithm. Performance analysis in algorithm design differs from conventional metrics, as the absolute running time depends on various factors, such as programming language, hardware, and system load. This module provides a comprehensive grasp of the critical concept of big-O notation, a cornerstone for assessing algorithm efficiency and performance. We'll explore this concept in the context of Javascript.
Common Patterns of Problems
Stacks and Queues
Linked Lists
Recursion
Sorting and Searching
Trees
Graphs
Dynamic Programming
Advanced Data Structures
Data structures and Algorithms in Javascript
About Lesson

Question

Determine whether the characters in a provided string can be rearranged to construct a palindrome. 

Explanation

A palindrome is a word or phrase that is the same forwards and backwards. A permutation is a rearrangement of letters. For a string to be a palindrome permutation, it should have at most one odd-count character.

Examples

Example 1:

  • Input: "Tact Coa"
  • Output: "true"
  • Explanation: returns True as permutations of Tact Coa are taco cat, atco cta, etc.

Constraints

  • The palindrome does not need to be limited to just dictionary words.
  • The words are not case-sensitive.

Practice

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut elit tellus, luctus nec ullamcorper mattis, pulvinar dapibus leo.
  • Utilize a character map to track the count of each character. Iterated through the counts to calculate the number of oddCounts.  Return true if oddCount is 1 or 0.
/** * Determine whether the characters in a provided * string can be rearranged to construct a palindrome. * @param {string} phrase * @return {boolean} */ const isPermutationOfPalindrome = (phrase) => { }; // some Tests from here const assert = require("assert"); // Test 1: String with an odd number of characters, is a permutation of a palindrome const test1Result = isPermutationOfPalindrome('tactcoapapa'); assert.strictEqual(test1Result, true, 'Test 1 failed'); // Test 2: String with an even number of characters, is a permutation of a palindrome const test2Result = isPermutationOfPalindrome('tactcooapapa'); assert.strictEqual(test2Result, true, 'Test 2 failed'); // Test 3: String is not case sensitive, with space and still a permutation of a palindrome const test3Result = isPermutationOfPalindrome('Tact Coa'); assert.strictEqual(test3Result, true, 'Test 3 failed'); // Test 4: String is not a permutation of a palindrome const test4Result = isPermutationOfPalindrome('tactcoaapa'); assert.strictEqual(test4Result, false, 'Test 4 failed'); console.log('All tests passed.');

Solution

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut elit tellus, luctus nec ullamcorper mattis, pulvinar dapibus leo.

Solution # 1: Using character map

const isPermutationOfPalindrome = (phrase) => {
    // count the character occurences in the phrase
    const charMap = {};
    for(let currentChar of phrase.toLowerCase()) {
      if(currentChar >= 'a' && currentChar <= 'z') {   
        charMap[currentChar] = (charMap[currentChar] || 0) + 1;
      }
    }
    
    // count the number of odd counts in above character map
    let oddCount = 0;
    for(const count of Object.values(charMap)) {
        if(count % 2 === 1) {
            oddCount++;
        }
    }
    
    // check if there is more than one odd count occurence
    return oddCount <= 1;
};

Explanation

  • Iterate through each character in the input phrase, and create a character map (charMap) to store the count of occurrences for each character.
  • Iterate over the values in the charMap to count the number of characters with an odd count.
  • Check if the count of characters with an odd occurrence (oddCount) is less than or equal to 1. If so, return true; otherwise, return false.

Time Complexity

  • O(n), where n is the length of the input string (phrase). The time complexity is determined by the two loops: one to iterate through the characters in the phrase and another to iterate through the values in the charMap. Both loops have a linear relationship with the size of the input string.

Space Complexity

  • O(k), where k is the number of unique characters in the input string. The space complexity is determined by the size of the charMap, which is proportional to the number of unique characters in the phrase.

Solution # 2: Using character array

const isPermutationOfPalindrome = (phrase) => {
  // count the character occurences in the phrase
  let countOdd = 0;
  const charArray = new Array(26).fill(0);
  for (const char of phrase.toLowerCase()) {
    const charCode = char.charCodeAt(0);
    if ('a'.charCodeAt(0) <= charCode && charCode <= 'z'.charCodeAt(0)) {
      const index = charCode - 'a'.charCodeAt(0);
      charArray[index] += 1;
      // increment countOdd if odd count is found
      if (charArray[index] % 2 === 1) {
        countOdd += 1;
      } else {
        countOdd -= 1;
      }
    }
  }

  return countOdd <= 1;
};

Explanation

  • In this solution we use a string array instead of a hashmap to make it more space-efficient.
  • Initialize countOdd to track characters with odd occurrences.
  • Create charArray to count each character’s occurrences. Iterate through lowercase characters in the phrase, updating charArray.
  • Increment countOdd for characters with odd counts; decrement for even counts.
  • Return true if the total count of characters with odd occurrences is at most 1.

Time Complexity

  • O(n), where n is the length of the input string (phrase). The time complexity is determined by the loop iterating through the characters in the phrase. 

Space Complexity

  • O(1) (constant space), as the size of charArray is fixed and independent of the input.

Comparison of two solutions

  • Both algorithms have the same time complexity, O(n), where n is the length of the input string. However, the space complexity differs.
  • The char code array version has a constant space complexity of O(1), while the hashmap version has a space complexity of O(k), where k depends on the number of unique characters in the input.
  • In scenarios, where the input string has a limited set of characters, the char code array version might be more space-efficient. The hashmap version, on the other hand, is more versatile and can handle inputs with a larger number of unique characters.