TinyURL是一种URL简化服务, 比如:当你输入一个URL https://leetcode.com/problems/design-tinyurl
时,它将返回一个简化的URL http://tinyurl.com/4e9iAk
.
要求:设计一个 TinyURL 的加密 encode
和解密 decode
的方法。你的加密和解密算法如何设计和运作是没有限制的,你只需要保证一个URL可以被加密成一个TinyURL,并且这个TinyURL可以用解密方法恢复成原本的URL。
方法一:使用简单的计数
public class Codec {
//根据次序存储加密前的url
private Map<Integer,String> map=new HashMap<>();
int count=0;
//加密后的url后面根的是加密的次序,解密时根据这个次序从map中查找就可以得到原url
public String encode(String longUrl) {
map.put(count,longUrl);
String shortUrl="http://tinyurl.com/"+count;
count++;
return shortUrl;
}
public String decode(String shortUrl) {
int index = shortUrl.lastIndexOf("/");
return map.get(Integer.valueOf(shortUrl.substring(index+1)));
}
}
方法 2:使用出现次序加密
将url的出现次序看做62进制,将每一位映射到chars字符中,用对应的字符作为key,同时作为加密
class Codec {
private String chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
private HashMap<String, String> map = new HashMap<>();
private int count = 0;
public String getKey() {
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 = getKey();
map.put(key, longUrl);
count++;
return "http://tinyurl.com/" + key;
}
public String decode(String shortUrl) {
int index = shortUrl.lastIndexOf("/");
return map.get(shortUrl.substring(index + 1));
}
}
方法一和方法二存在的问题:
- 可加密的数目依赖int
- 加密后的不一定更短
- 容易预测
方法三:使用HashCode
class Codec {
private HashMap<Integer, String> map = new HashMap<>();
public String encode(String longUrl) {
Integer key = longUrl.hashCode();
map.put(key, longUrl);
return "http://tinyurl.com/" + key;
}
public String decode(String shortUrl) {
int index = shortUrl.lastIndexOf("/");
return map.get(Integer.valueOf(shortUrl.substring(index + 1)));
}
}
特点:
- 加密的数目依赖int,hashCode是int的
- 加密后的长度与原来长度没有直接关系
- 不同的url的hashCode可能相同
- 不容易预测
方法四:使用随机数
class Codec {
private HashMap<Integer, String> map = new HashMap<>();
private Random random=new Random();
public String encode(String longUrl) {
Integer key =random.nextInt(Integer.MAX_VALUE);
map.put(key, longUrl);
return "http://tinyurl.com/" + key;
}
public String decode(String shortUrl) {
int index = shortUrl.lastIndexOf("/");
return map.get(Integer.valueOf(shortUrl.substring(index + 1)));
}
}
特点:
- 加密的数目依赖int
- 加密后的长度与原来长度没有直接关系
- 可能冲突
- 不容易预测
方法五:随机固定长度加密
class Codec {
String chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
HashMap<String, String> map = new HashMap<>();
Random rand = new Random();
public String getRand() {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 6; i++) {
sb.append(chars.charAt(rand.nextInt(62)));
}
return sb.toString();
}
public String encode(String longUrl) {
String key = getRand();
while (map.containsKey(key)) {
key = getRand();
}
map.put(key, longUrl);
return "http://tinyurl.com/" + key;
}
public String decode(String shortUrl) {
int index = shortUrl.lastIndexOf("/");
return map.get(shortUrl.substring(index + 1));
}
}
特点:
- 可加密数目大,也好扩展数目
- 冲突可能小
- 长度固定
- 不可预测
总结
用一个map存原始url,key跟在加密后的url,解密根据这个key查找
不同的加密方法就是key的策略不同,从而影响可加密数量、长度、预测情况