Difficulty: 🟡 Medium
Note: This is a companion problem to the System Design problem: Design TinyURL. TinyURL is a URL shortening service where you enter a URL such as
https://leetcode.com/problems/design-tinyurl
and it returns a short URL such ashttp://tinyurl.com/4e9iAk
. Design a class to encode a URL and decode a tiny URL.
There is no restriction on how your encode/decode algorithm should work. You just need to ensure that a URL can be encoded to a tiny URL and the tiny URL can be decoded to the original URL.
Implement the Solution
class:
Solution()
Initializes the object of the system.String encode(String longUrl)
Returns a tiny URL for the givenlongUrl
.String decode(String shortUrl)
Returns the original long URL for the givenshortUrl
. It is guaranteed that the givenshortUrl
was encoded by the same object.
Example 1:
Input: url = "https://leetcode.com/problems/design-tinyurl"
Output: "https://leetcode.com/problems/design-tinyurl"
Explanation:
Solution obj = new Solution();
string tiny = obj.encode(url); // returns the encoded tiny url.
string ans = obj.decode(tiny); // returns the original url after decoding it.
1 <= url.length <= 104
url
is guranteed to be a valid URL.
During class instance initialization we initialize key_value_store
(in production Redis like distributed key value will be used) variable and define
constant variables for short_url_template
, code_length
and random_string_length
.
In order to get shortUrl
we first generate code
by calculating sha256
digest,
then encode digest using base64
and slice only 7 (code_length
) characters.
If generated code
is not already in our key_value_store
build shortUrl
and return.
Otherwise, reginarate code
by appending random string to longUrl
.
Similar approach is used in real production.
import base64
import random
import string
import hashlib
class Codec:
def __init__(self):
self._code_length = 7
self._random_string_length = 5
self._key_value_store = {}
self._short_url_template = "http://tinyurl.com/{code}"
def _get_code(self, url):
return base64.b64encode(hashlib.sha256(url.encode('utf-8')).digest()).decode("utf-8")[:self._code_length]
def _get_random_string(self):
return ''.join(random.choices(string.ascii_uppercase + string.ascii_lowercase, k=self._random_string_length))
def encode(self, longUrl: str) -> str:
"""Encodes a URL to a shortened URL.
"""
while True:
code = self._get_code(longUrl)
if code not in self._key_value_store:
break
longUrl += self._get_random_string()
shortUrl = self._short_url_template.format(code=code)
self._key_value_store[shortUrl] = longUrl
return shortUrl
def decode(self, shortUrl: str) -> str:
"""Decodes a shortened URL to its original URL.
"""
return self._key_value_store.get(shortUrl, "")
# Your Codec object will be instantiated and called as such:
# codec = Codec()
# codec.decode(codec.encode(url))
NB: If you want to get community points please suggest solutions in other languages as merge requests.