原题:

TinyURL是一种URL简化服务, 比如:当你输入一个URL https://leetcode.com/problems/design-tinyurl 时,它将返回一个简化的URL http://tinyurl.com/4e9iAk.

要求:设计一个 TinyURL 的加密 encode 和解密 decode 的方法。你的加密和解密算法如何设计和运作是没有限制的,你只需要保证一个URL可以被加密成一个TinyURL,并且这个TinyURL可以用解密方法恢复成原本的URL。

解法:

随机数

大致框架:
# # class Codec:#     def encode(self, longUrl: str) -> str:
#         """Encodes a URL to a shortened URL.
#         """
#     def decode(self, shortUrl: str) -> str:
#         """Decodes a shortened URL to its original URL.
#         """
代码:
import random
class Codec:"""URL简化类:将一个长url转化为一个短url(转换后的 URL路径 为6位数的字母或数字)转化算法:使用 62 位由大小写字母和数字构成的字符串集合 作为 【62进制位表】,可表示的 6位url 数量为 62 ** 6 == 586亿多,几亿次以内的调用不用担心字典键冲突,不够用的话可以再增加进制位数。"""_chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"_dict = {}_key = ''.join(random.sample(_chars, 6))@classmethoddef get_rand(cls):return ''.join(random.sample(cls._chars, 6))@classmethoddef encode(cls, long_url):"""将一个 长URL 编码为一个 短URL【随机固定长度加密】。使用 random 模块 随机从 62 位字符串中选取 6 个作为 URL短路径。因为使用了随机数,根据 short_url 来预测字典大小几乎是不可能的,数据更加安全。"""while cls._dict.get(cls._key):cls._key = cls.get_rand()cls._dict[cls._key] = long_urlreturn 'http://tinyurl.com/' + cls._key@classmethoddef decode(cls, short_url):"""将一个 短URL 解码为一个 长URL。直接根据 url字符串后6位,从字典中取值。"""return cls._dict[short_url[19:]]# Your Codec object will be instantiated and called as such:
# codec = Codec()
# codec.decode(codec.encode(url))

使用简单的计数 [Accepted]

为了加密 URL,我们使用计数器 (i)(i)(i) ,每遇到一个新的 URL 都加一。我们将 URL 与它的次数 iii 放在哈希表 HashMap 中,这样我们在稍后的解密中可以轻易地获得原本的 URL。

public class Codec {Map<Integer, String> map = new HashMap<>();int i = 0;public String encode(String longUrl) {map.put(i, longUrl);return "http://tinyurl.com/" + i++;}public String decode(String shortUrl) {return map.get(Integer.parseInt(shortUrl.replace("http://tinyurl.com/", "")));}
}

分析:

可以加密解密的 URL 数目受限于int 所能表示的范围。

如果超过int 个 URL 需要被加密,那么超过范围的整数会覆盖之前存储的 URL,导致算法失效。

URL 的长度不一定比输入的 longURL 短。它只与加密的 URL 被加密的顺序有关。

这个方法的问题是预测下一个会产生的加密 URL 非常容易,因为产生几个 URL 后很容易推测出生成的模式。

使用出现次序加密

这种方法中,我们将当前 URL 第几个出现作为关键字进行加密,将这个出现次序看做 62 进制,并将每一位映射到一个长度为 62 位的表中对应的字母作为哈希值。此方法中,我们使用一系列整数和字母表来加密,而不是仅仅使用数字进行加密。

public class Codec {String chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";HashMap<String, String> map = new HashMap<>();int count = 1;public String getString() {int c = count;StringBuilder sb = new StringBuilder();while (c > 0) {c--;sb.append(chars.charAt(c % 62));c /= 62;}return sb.toString();}public String encode(String longUrl) {String key = getString();map.put(key, longUrl);return "http://tinyurl.com/" + key;count++;}public String decode(String shortUrl) {return map.get(shortUrl.replace("http://tinyurl.com/", ""));}
}

分析:

可加密的 URL 数目还是依赖于 int 的范围。因为相同的 countcount 在出现次序溢出整数范围后仍然会出现。

加密后 URL 的长度不一定更短,但某种程度上与 longURL 的出现次序相对独立。比方说产生的 URL
长度按顺序会是 1(62次),2(62次)。

这个算法的表现比较好,因为相同的加密结果只有在溢出整数后才会发生,这个范围非常大。

如果出现重复,下一次产生的加密结果还是能通过某种计算被预测出来。

hashcode

public class Codec {Map<Integer, String> map = new HashMap<>();public String encode(String longUrl) {map.put(longUrl.hashCode(), longUrl);return "http://tinyurl.com/" + longUrl.hashCode();}public String decode(String shortUrl) {return map.get(Integer.parseInt(shortUrl.replace("http://tinyurl.com/", "")));}
}

分析

可加密 URL 的数目由int 决定,因为hashCode 使用整数运算。

加密后 URL 的平均长度与 \text{longURL}longURL 的长度没有直接关联。

hashCode() 对于不同的字符串不一定产生独一无二的加密后
URL。像这样对于不同输入产生相同输出的过程叫做冲突。因此,如果加密字符串的数目增加,冲突的概率也会增加,最终导致算法失效。

下图展示了不同对象映射到相同的 hashcode,以及对象越多冲突概率越大。
可能几个字符串加密后冲突就会发生,会远比 \text{int}int 要小。这与生日悖论类似,也就是如果有23个人,存在 2 个人同一天生日的概率达到 50%,如果有 70 个人,这一概率会高达 99.9%。

这种方法中,很难根据前面产生的 URL 结果预测后面加密 URL 的答案。

加密和解码(不同加密方法:随机数,hash,出现次数)相关推荐

  1. 前端加密的常见场景和方法

    前端加密的常见场景和方法 首先,加密的目的,简而言之就是将明文转换为密文.甚至转换为其他的东西, 用来隐藏明文内容本身,防止其他人直接获取到敏感明文信息.或者提高其他 人获取到明文信息的难度.通常我们 ...

  2. go-dongle 0.2.0 版本发布了,一个轻量级、语义化的 golang 编码解码、加密解密库

    dongle 是一个轻量级.语义化.对开发者友好的 Golang 编码解码和加密解密库 Dongle 已被 awesome-go 收录, 如果您觉得不错,请给个 star 吧 github.com/g ...

  3. C#开发中关于加密解密字符串的使用方法

    C#开发中关于加密解密字符串的使用方法 C#加密解密字符串方法 首先在web.config | app.config 文件下增加如下代码: <?xml version="1.0&quo ...

  4. python连接sqlite加密_C#连接加密的Sqlite数据库的方法

    对数据加密分两种,一种是对数据库本身进行加密,另一种是对数据表中的数据进行加密, 如果SQLite数据库加密,我这里使用的一个管理工具叫SQLiteDeveloper,如下就可以加密数据库 , 如果在 ...

  5. java中完成md5加密解密_java实现md5加密解密 notNET中加密和解密的实现方法

    java实现md5加密解密 notNET中加密和解密的实现方法 亦或是旅途风光 7-14 1918℃ 22 [ ee21.cn - ASP.NET ] .NET将原来独立的API和SDK合并到一个框架 ...

  6. .NET中加密和解密的实现方法

    来自csdn redbb,转载请标明原作者!! .NET将原来独立的API和SDK合并到一个框架中,这对于程序开发人员非常有利.它将CryptoAPI改编进.NET的System.Security.C ...

  7. PDF加密如何加密?分享两个方法给你

    如今办公已经进入了信息时代,越来越多的小伙伴喜欢使用电子文档,对于办公人士来说也比较的方便,因此PDF文件是很多人经常使用的文档格式,但有的时候,为了防止自己的文件被他人盗用,就会利用一些软件来给自己 ...

  8. veracrypt加密mysql_VeraCrypt怎么用 VeraCrypt加密文件的图文教程方法

    目前由很多电脑文件加密方法,比如常见的隐藏,压缩加密,还有借助第三方加密工具进行加密等等,通常情况下,第三方加密工具都是收费的,这里闪电吧的小编说说如何使用VeraCrypt免费工具给电脑加密.Ver ...

  9. Linux环境下脚本加密软件SHC的解密方法

    Linux环境下脚本加密软件SHC的解密方法 2016/08/06:更新一个新的解密脚本 https://github.com/yanncam/UnSHc 自从我在博客里面发布了一些免流相关的东西之后 ...

最新文章

  1. Error: Most middleware (like bodyParser) ...
  2. 【UR #4】元旦三侠的游戏(博弈论+记忆化)
  3. 解读三组容易混淆的Dockerfile指令
  4. JavaFX官方教程(六)之带有JavaFX CSS的花式表单
  5. python中定义数据结构_Python中的数据结构—简介
  6. NachOS简述和源文件
  7. DBS:CUPhone
  8. 市盈率相对盈利增长比率PEG
  9. c语言求100以内偶数和while,c语言 求1到100以内的偶数之和
  10. Excel如何将文本中间的数值提取出来
  11. 千里之遥看樱花,“东湖·樱园”元宇宙
  12. 使用requests爬虫制作自己的天气预报“Api”
  13. 20135220谈愈敏-期末总结
  14. android 模拟器 blue,Win下的Android模拟器BlueStacks
  15. Android数据加密传输
  16. MES与ERP的集成
  17. 【树莓派4B学习】二、树莓派4B介绍与一些必要的软件安装配置
  18. WINDOWS PE制作 - 主引导记录(Master Boot Record)介绍
  19. 【电气专业知识问答】问:预防高压配电装置载流回路过热的措施有哪些?
  20. outline的使用

热门文章

  1. Python3小程序:把字符串转换成连续的UTF8编码(16位)
  2. 数据逻辑讨论计算机,1绪论信息技术算法与程序福建教师招考.ppt
  3. 遍历结果集java_java – 循环遍历while循环后如何将结果集重置为第一行
  4. c++ 模糊搜索 正则表达式_c++使用正则表达式提取关键字的方法
  5. java executequery_java execute、executeQuery和executeUpdate之间的区别
  6. 左右声道测试_小说:少年参加测试,直接挑战十只狗恐兽,众人见了惊呼:SS级...
  7. mysql大数据量的全量备份_mysql备份神器——Xtrabackup全量备份还原
  8. 清空运行中的jar 日志_Java日志体系权威总结
  9. js 延迟几秒执行ifarme_Node.js调试之llnode篇
  10. mysql主从不同步问题_mysql主从之间不同步问题