来源:力扣(LeetCode)
描述:
TinyURL 是一种 URL 简化服务, 比如:当你输入一个 URL https://leetcode.com/problems/design-tinyurl 时,它将返回一个简化的URL http://tinyurl.com/4e9iAk 。请你设计一个类来加密与解密 TinyURL 。
加密和解密算法如何设计和运作是没有限制的,你只需要保证一个 URL 可以被加密成一个 TinyURL ,并且这个 TinyURL 可以用解密方法恢复成原本的 URL 。
实现 Solution 类:
- Solution() 初始化 TinyURL 系统对象。
- String encode(String longUrl) 返回 longUrl 对应的 TinyURL 。
- String decode(String shortUrl) 返回 shortUrl 原本的 URL 。题目数据保证给定的 shortUrl 是由同一个系统对象加密的。
示例:
输入:url = "https://leetcode.com/problems/design-tinyurl" 输出:"https://leetcode.com/problems/design-tinyurl" 解释: Solution obj = new Solution(); string tiny = obj.encode(url); // 返回加密后得到的 TinyURL 。 string ans = obj.decode(tiny); // 返回解密后得到的原本的 URL 。
提示:
- 1 <= url.length <= 104
- 题目数据保证 url 是一个有效的 URL
前言
题目不要求相同的 URL 必须加密成同一个 TinyURL,因此本文的方法不满足相同的 URL 加密成同一个 TinyURL。如果想要实现相同的 URL 加密成同一个 TinyURL,则额外保存一个从 URL 到 TinyURL 的映射。
方法一:自增
Encode 函数
使用自增 id 作为 longUrl 的键,每接收一个 longUrl 都将 id 加一,将键值对 (id,longUrl) 插入数据库 dataBase,然后返回带有 textit{id}id 的字符串作为 shorUrl。
Decode 函数
将 shortUrl 转换成对应的 }key,然后在数据库 dataBase 中查找 key 对应的 longUrl。
代码:
class Solution {
private:
unordered_map dataBase;
int id;
public:
Solution() {
id = 0;
}
string encode(string longUrl) {
id++;
dataBase[id] = longUrl;
return string("http://tinyurl.com/") + to_string(id);
}
string decode(string shortUrl) {
int p = shortUrl.rfind('/') + 1;
int key = stoi(shortUrl.substr(p, int(shortUrl.size()) - p));
return dataBase[key];
}
};
执行用时:4 ms, 在所有 C++ 提交中击败了70.90%的用户
内存消耗:6.8 MB, 在所有 C++ 提交中击败了36.81%的用户
复杂度分析
时间复杂度:
Encode 函数: O(n),其中 n 是字符串 longUrl 的长度。
Decode 函数: O(1)。我们当 shortUrl 当成有限长度的字符串看待。
空间复杂度:
Encode 函数: O(n)。保存字符串 longUrl 需要 O(n) 的空间。
Decode 函数: O(1)。
方法二:哈希生成
代码:
const long long k1 = 1117;
const long long k2 = 1e9 + 7;
class Solution {
private:
unordered_map dataBase;
unordered_map urlToKey;
public:
Solution() {
}
string encode(string longUrl) {
if (urlToKey.count(longUrl) > 0) {
return string("http://tinyurl.com/") + to_string(urlToKey[longUrl]);
}
long long key = 0, base = 1;
for (auto c : longUrl) {
key = (key + c * base) % k2;
base = (base * k1) % k2;
}
while (dataBase.count(key) > 0) {
key = (key + 1) % k2;
}
dataBase[key] = longUrl;
urlToKey[longUrl] = key;
return string("http://tinyurl.com/") + to_string(key);
}
string decode(string shortUrl) {
int p = shortUrl.rfind('/') + 1;
int key = stoi(shortUrl.substr(p, int(shortUrl.size()) - p));
return dataBase[key];
}
};
执行用时:0 ms, 在所有 C++ 提交中击败了100.00%的用户
内存消耗:7 MB, 在所有 C++ 提交中击败了10.69%的用户
方法三:随机生成
代码:
class Solution {
private:
unordered_map dataBase;
public:
Solution() {
srand(time(0));
}
string encode(string longUrl) {
int key;
while (true) {
key = rand();
if (dataBase.count(key) == 0) {
break;
}
}
dataBase[key] = longUrl;
return string("http://tinyurl.com/") + to_string(key);
}
string decode(string shortUrl) {
int p = shortUrl.rfind('/') + 1;
int key = stoi(shortUrl.substr(p, int(shortUrl.size()) - p));
return dataBase[key];
}
};
执行用时:4 ms, 在所有 C++ 提交中击败了70.90%的用户
内存消耗:6.8 MB, 在所有 C++ 提交中击败了31.09%的用户
author:LeetCode-Solution



