力扣每日一题0629-535. TinyURL 的加密与解密

92 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第29天,点击查看活动详情

TinyURL 是一种 URL 简化服务, 比如:当你输入一个 URL leetcode.com/problems/de… 时,它将返回一个简化的URL 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 。

自增

  • Encode 函数

    使用自增 id\textit{id} 作为 longUrl\textit{longUrl} 的键,每接收一个 longUrl\textit{longUrl} 都将 id\textit{id} 加一,将键值对 (id,longUrl)(\textit{id}, \textit{longUrl}) 插入数据库 dataBase\textit{dataBase},然后返回带有 id\textit{id} 的字符串作为 shorUrl\textit{shorUrl}

  • Decode 函数

    \textit{shortUrl}\ 转换成对应的 key\textit{key},然后在数据库 dataBase\textit{dataBase} 中查找 key\textit{key} 对应的 longUrl\textit{longUrl}

var encode = function(longUrl) {
    this.dataBase = new Map();
    this.id = 0;
    this.id++;
    this.dataBase.set(this.id, longUrl);
    return "<http://tinyurl.com/>" + this.id;
};

var decode = function(shortUrl) {
    const p = shortUrl.lastIndexOf('/') + 1;
    const key = parseInt(shortUrl.substring(p));
    return this.dataBase.get(key);
};

哈希生成

  • Encode 函数

    设字符串 longUrl\textit{longUrl} 的长度为 nn,选择两个合适的质数 k1=1117k_1 = 1117k2=109+7k_2 = 10^9 + 7,使用以下方法来计算 longUrl\textit{longUrl} 的哈希值:

    Hash(longUrl)=(n1i=0longUrl[i]×ki1)modk2Hash(longUrl)=(∑^{i=0}_{n−1}longUrl[i]×k^1_i)modk_2

    将哈希值作为 longUrl\textit{longUrl}key\textit{key},将键值对 (key,longUrl)(\textit{key}, \textit{longUrl}) 插入数据库 dataBase\textit{dataBase},然后返回带有 key\textit{key} 的字符串作为 shorUrl\textit{shorUrl}

    发生哈希冲突时,我们采用线性探测再散列的方法,将 key\textit{key} 加一,直到没有冲突。相同的 longUrl\textit{longUrl} 的哈希值相同,因此哈希冲突会频繁发生。为了避免这一点,我们使用一个额外的哈希表记录从 longUrl\textit{longUrl}key\textit{key} 的映射。

  • Decode 函数

    \textit{shortUrl}\ 转换成对应的 key\textit{key},然后在数据库 dataBase\textit{dataBase} 中查找 key\textit{key} 对应的 longUrl\textit{longUrl}

var encode = function(longUrl) {
    const K1 = 1117;
    const K2 = 1000000007;
    this.dataBase = new Map();
    this.urlToKey = new Map();

    if (this.urlToKey.has(longUrl)) {
            return "<http://tinyurl.com/>" + this.urlToKey.get(longUrl);
        }
        let key = 0;
        let base = 1;
        for (let i = 0; i < longUrl.length; i++) {
            const c = longUrl[i];
            key = (key + c * base) % K2;
            base = (base * K1) % K2;
        }
        while (dataBase.has(key)) {
            key = (key + 1) % K2;
        }
        dataBase.set(key, longUrl);
        urlToKey.set(longUrl, key);
        return "<http://tinyurl.com/>" + key;
};

var decode = function(shortUrl) {
    const p = shortUrl.lastIndexOf('/') + 1;
    const key = parseInt(shortUrl.substring(p));
    return this.dataBase.get(key);
};