首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >LeetCode 535:编解码TinyURL

LeetCode 535:编解码TinyURL
EN

Code Review用户
提问于 2020-10-20 18:59:22
回答 3查看 581关注 0票数 3

我正在为LeetCode的“编码和解码TinyURL”发布一个解决方案。如果你想复习,请看。谢谢!

问题

TinyURL是一个URL缩短服务,您可以在其中输入一个URL (如https://leetcode.com/problems/design-tinyurl ),它返回一个短URL (如http://tinyurl.com/4e9iAk )。

encode服务设计TinyURL和decode方法。对于编码/解码算法的工作方式没有任何限制。您只需要确保URL可以被编码成一个微小的URL,并且这个微小的URL可以被解码到原始的URL。

代码语言:javascript
复制
// The following block might slightly improve the execution time;
// Can be removed;
static const auto __optimize__ = []() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    std::cout.tie(nullptr);
    return 0;
}();

// Most of headers are already included;
// Can be removed;
#include <iostream>
#include <cstdint>
#include <string>
#include <unordered_map>
#include <utility>
#include <random>

static const struct Solution {
    public:
        const std::string encode(
            const std::string long_url
        ) {
            std::string tiny_encoded;

            if (!encoded_url.count(long_url)) {
                for (auto index = 0; index < kTinySize; ++index) {
                    tiny_encoded.push_back(char_pool[rand_generator() % std::size(char_pool)]);
                }

                encoded_url.insert(std::pair<std::string, std::string>(long_url, tiny_encoded));
                decoded_url.insert(std::pair<std::string, std::string>(tiny_encoded, long_url));

            } else {
                tiny_encoded = encoded_url[long_url];
            }

            return kDomain + tiny_encoded;
        }

        const std::string decode(
            const std::string short_url
        ) {

            return std::size(short_url) != kDomainTinySize ||
                   !decoded_url.count(short_url.substr(kDomainSize, kTinySize)) ? "" :
                   decoded_url[short_url.substr(kDomainSize, kTinySize)];
        }

    private:
        static constexpr char kDomain[] = "http://tinyurl.com/";
        static constexpr unsigned int kTinySize = 6;
        static constexpr unsigned int kDomainSize = std::size(kDomain) - 1;
        static constexpr auto kDomainTinySize = kDomainSize + kTinySize;
        static constexpr char char_pool[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        std::unordered_map<std::string, std::string> encoded_url;
        std::unordered_map<std::string, std::string> decoded_url;
        std::random_device rand_generator;
};

// Your Solution object will be instantiated and called as such:
// Solution solution;
// solution.decode(solution.encode(url));
EN

回答 3

Code Review用户

回答已采纳

发布于 2020-10-20 19:22:08

你正在做两次查找。

代码语言:javascript
复制
            if (!encoded_url.count(long_url)) {

                .. stuff

            } else {
                tiny_encoded = encoded_url[long_url];
            }

我知道它是用于查找的O(1)。但这里面有一个真正的常数。如果你可以的话,尽量避免。

使用find()。那么,如果它在那里,你可以简单地使用它。

代码语言:javascript
复制
            auto find = encoded_url.find(long_url);
            if (find == encoded_url.end()) {

                .. stuff

            } else {
                tiny_encoded = find->second;
            }

这是伟大的,如果你想要随机的URL是很难猜测的。

代码语言:javascript
复制
                for (auto index = 0; index < kTinySize; ++index) {
                    tiny_encoded.push_back(char_pool[rand_generator() % std::size(char_pool)]);
                }

但这是谜题的要求吗。看起来(不确定产生随机数的代价有多大)这样的方式产生一个名字是非常昂贵的。

也有可能发生冲突。如果使用的是随机生成的值,则在末尾附加时间戳以避免冲突。

就我个人而言,我不喜欢指定类型。但是,如果要这样做,请使用方法的类型,而不是特定的类型:

代码语言:javascript
复制
    encoded_url.insert(std::pair<std::string, std::string>(long_url, tiny_encoded));


    // Top of the class.
    using Map      = std::unordered_map<std::string, std::string>;
    using MapValue = Map::value_type;

    // In the code.
    encoded_url.insert(MapValue(long_url, tiny_encoded));

但我想我会简单地使用emplace()

代码语言:javascript
复制
    encoded_url.emplace(long_url, tiny_encoded);
票数 4
EN

Code Review用户

发布于 2020-10-20 20:03:05

我同意马丁约克回答的每一件事。只有一件事:如果你不创建一个纯粹随机的网址,而是通过散列原始网址来创建一个,你可以避免拥有两个unordered_maps。这样,您将始终为相同的长URL创建相同的小URL,因此您不再需要encoded_url了。当然,您仍然需要处理以某种方式中的副本。

票数 3
EN

Code Review用户

发布于 2020-10-20 22:02:54

其他人说得很好,但我要加上一个文体上的小测验。

代码语言:javascript
复制
return std::size(short_url) != kDomainTinySize ||
       !decoded_url.count(short_url.substr(kDomainSize, kTinySize)) ? "" :
       decoded_url[short_url.substr(kDomainSize, kTinySize)];

是一条该死的单线船。三元操作符很有趣,但作为一个绝对滥用它的人来说,如果你不能让它舒适地放在一两行线上,那么当你在6个月后回去读它时,你会恨自己的。此外,当你看到许多!s四处奔走时,通常是打破德摩根定律的时候了。这会让我们把这条无趣的路远远地抛在视线之外。所以,如果我们真的想要三元..。

代码语言:javascript
复制
return std::size(short_url) == kDomainTinySize &&
       decoded_url.count(short_url.substr(kDomainSize, kTinySize)) ?
       decoded_url[short_url.substr(kDomainSize, kTinySize)] :
       "";

或者如果我觉得有点大胆,也许甚至

代码语言:javascript
复制
return std::size(short_url) == kDomainTinySize 
       && decoded_url.count(short_url.substr(kDomainSize, kTinySize))
       ? decoded_url[short_url.substr(kDomainSize, kTinySize)]
       : "";

我撒谎了,第二点:我认为惯用的C++也应该尽可能少地依赖于隐式类型转换,也就是说,将该条件更改为decoded_url.count(...) != 0。这是更详细,但它也立即更清楚的读者是什么意思。不过,理智的人可能会不同意。

票数 3
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/250921

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档