As a follow up for Tiny URL, we are going to support custom tiny url, so that user can create their own tiny url.

Notice

Custom url may have more than 6 characters in path.

Have you met this question in a real interview?

Yes

Example

createCustom("http://www.lintcode.com/", "lccode")

>
>
 http://tiny.url/lccode
createCustom("http://www.lintcode.com/", "lc")

>
>
 error
longToShort("http://www.lintcode.com/problem/")

>
>
 http://tiny.url/1Ab38c   // this is just an example, you can have you own 6 characters.
shortToLong("http://tiny.url/lccode")

>
>
 http://www.lintcode.com/
shortToLong("http://tiny.url/1Ab38c")

>
>
 http://www.lintcode.com/problem/
shortToLong("http://tiny.url/1Ab38d")

>
>
 null
#include <cstdint>
using namespace std;

class TinyUrl2 {
public:
    /**
     * @param long_url a long url
     * @param a short key
     * @return a short url starts with http://tiny.url/
     */
    string createCustom(string& long_url, string& short_key) {
        // Write your code here
        string short_url = TINYURL + short_key;
        uint64_t id = shortKey2Id(short_key);

        if (id2url.find(id) != id2url.end() && 
            id2url[id] != long_url)
            return "error";

        if (url2id.find(long_url) != url2id.end() && 
            url2id[long_url] != id)
            return "error";

        if (id2url.find(id) != id2url.end() ||
            url2id.find(long_url) != url2id.end()) {
            return short_url;
        }

        if (custom_l2s.find(long_url) != custom_l2s.end() &&
            custom_l2s[long_url] != short_url) 
            return "error";

        if (custom_s2l.find(short_url) != custom_s2l.end() &&
            custom_s2l[short_url] != long_url) 
            return "error";

        custom_l2s[long_url] = short_url;
        custom_s2l[short_url] = long_url;

        return short_url;
    }

    /**
     * @param long_url a long url
     * @return a short 
     * url starts with http://tiny.url/
     */
    string longToShort(string& long_url) {
        // Write your code here
        if (custom_l2s.find(long_url) != custom_l2s.end())
            return custom_l2s[long_url];

        uint64_t id = 0;
        for (auto ch : long_url) {
            id = (id * 256ULL + ch) % MAX_ID;
        }

       if (url2id.find(long_url) != url2id.end()) {
           id = url2id[long_url];
       } else {
            while (id2url.find(id) != id2url.end() && id2url[id] != long_url)
            ++id;
       }

        id2url[id] = long_url;
        url2id[long_url] = id;

        string shortKey = id2ShortKey(id);

        return TINYURL + shortKey;
    }

    /**
     * @param short_url a short url starts with http://tiny.url/
     * @return a long url
     */
    string shortToLong(string& short_url) {
        // Write your code here
        if (custom_s2l.find(short_url) != custom_s2l.end())
            return custom_s2l[short_url];

        string shortKey = getShortKey(short_url);
        uint64_t id = shortKey2Id(shortKey);

        return id2url[id];
    }

private:
    map<string, string> custom_l2s;
    map<string, string> custom_s2l;
    map<uint64_t, string> id2url;
    map<string, uint64_t> url2id;


    const string TINYURL = "http://tiny.url/";
    const uint64_t MAX_ID = 56800235584ULL;

    string id2ShortKey(uint64_t id) {
        char c[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        string res;
        while (id > 0) {
            res += c[id % 62];
            id /= 62;
        }
        while (res.length() < 6) {
            res += 'a';
        }

        std::reverse(res.begin(), res.end());
        return res;
    }

    string getShortKey(string & short_url) {
        return short_url.substr(TINYURL.size());
    }

    uint64_t shortKey2Id(string &shortKey) {
        uint64_t id = 0;
        for (char ch : shortKey) {
            if (ch >= 'a' && ch <= 'z')
                id = id * 62 + ch - 'a';
            if (ch >= 'A' && ch <= 'Z')
                id = id * 62 + ch - 'A' + 26;
            if (ch >= '0' && ch <= '9')
                id = id * 62 + ch - '0' + 52;
        }
        return id;
    }

};

results matching ""

    No results matching ""