Design Gurus Logo
Solution: Encode and Decode Strings
Go Back

Problem Statement

Given a list of strings, your task is to develop two functions: one that encodes the list of strings into a single string, and another that decodes the resulting single string back into the original list of strings. It is crucial that the decoded list is identical to the original one.

It is given that you can use any encoding technique to encode list of string into the single string.

Examples

  1. Example 1:

    • Input: ["apple", "banana"]
    • Expected Output: ["apple", "banana"]
    • Justification: When we encode the input strings ["apple", "banana"], we get a single encoded string. Decoding this encoded string should give us the original list ["apple", "banana"].
  2. Example 2:

    • Input: ["sun", "moon", "stars"]
    • Expected Output: ["sun", "moon", "stars"]
    • Justification: After encoding the input list, decoding it should bring back the original list.
  3. Example 3:

    • Input: ["Hello123", "&*^%"]
    • Expected Output: ["Hello123", "&*^%"]
    • Justification: Regardless of the content of the string (special characters, numbers, etc.), decoding the encoded list should reproduce the original list.

Constraints:

  • 1 <= strs.length <= 200
  • 0 <= strs[i].length <= 200
  • strs[i] contains any possible characters out of 256 valid ASCII characters.

Solution

Our approach will utilize a delimiter that doesn't appear in the input strings. For the sake of simplicity, we can choose a character like #. If # is possible in the input, we can use multiple characters like ## to reduce the chance it appears in the input.

  1. Encoding:

    • For each string in the list, we append it to the encoded string.
    • After appending the string, we add the delimiter ##.
    • Continue this for all the strings in the list.
  2. Decoding:

    • We split the encoded string using our delimiter ##.
    • This will give us a list of strings which is our original list.
  3. Handling Edge Cases:

    • If ## can be part of the input strings, then our approach will fail. To handle such cases, we can prefix each string with its length followed by a special character, like |, before the actual string. This way, during decoding, we can use the length to identify the end of one string and the beginning of the next.

Algorithm Walkthrough

Let's walk through the algorithm using the input ["apple", "banana##cherry"]:

  1. During encoding:
    • "apple" becomes "5|apple##"
    • "banana##cherry" becomes "15|banana##cherry##"
    • The final encoded string is "5|apple##15|banana##cherry##"
  2. During decoding:
    • Read the first character, which is 5. It tells us the next 5 characters form the first string "apple".
    • The next character # is part of our delimiter, so we skip two characters.
    • Next, read the number 15, which tells us the next 15 characters form the string "banana##cherry".
    • Finally, we reach the end of our encoded string.

Code

Python3
Python3

Complexity Analysis

  • Time Complexity:

    • For encoding, it is (O(n)), where (n) is the combined length of all the strings in the list because we iterate over each character once.
    • For decoding, it's also (O(n)) for the same reason.
  • Space Complexity: (O(n)) as we store the encoded version of the string, and its length is proportional to the combined length of all the strings in the list.