Note: This is a companion problem to the System Design problem: Design TinyURL.
TinyURL is a URL shortening service where you enter a URL such as https://leetcode.com/problems/design-tinyurl and it returns a short URL such as http://tinyurl.com/4e9iAk.
Design the encode and decode methods for the TinyURL service. There is no restriction on how your encode/decode algorithm should work. You just need to ensure that a URL can be encoded to a tiny URL and the tiny URL can be decoded to the original URL.
answer one
public class Codec {
Map<String, String> index = new HashMap<String, String>();
Map<String, String> revIndex = new HashMap<String, String>();
static String BASE_HOST = "http://tinyurl.com/";
// Encodes a URL to a shortened URL.
public String encode(String longUrl) {
if (revIndex.containsKey(longUrl)) return BASE_HOST + revIndex.get(longUrl);
String charSet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
String key = null;
do {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 6; i++) {
int r = (int) (Math.random() * charSet.length());
sb.append(charSet.charAt(r));
}
key = sb.toString();
} while (index.containsKey(key));
index.put(key, longUrl);
revIndex.put(longUrl, key);
return BASE_HOST + key;
}
// Decodes a shortened URL to its original URL.
public String decode(String shortUrl) {
return index.get(shortUrl.replace(BASE_HOST, ""));
}
}
answer two
public class TinyUrlEncodeDecode {
private static final String SEED = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
private static final String BASE = "http://tinyurl.com/";
private static Map<String, String> keyToURL = new HashMap<>();
private static Map<String, String> urlToKey = new HashMap<>();
public static void main(String[] args) {
String tinyURL = encode("http://thisislongurl.com/abcd/123");
String longURL = decode(tinyURL);
System.out.println("tinyURL = " + tinyURL);
System.out.println("longURL = " + longURL);
}
public static String encode(String longUrl) {
if (longUrl == null || longUrl.isEmpty()) {
return null;
}
if (urlToKey.containsKey(longUrl)) {
return BASE + urlToKey.get(longUrl);
}
StringBuilder key = null;
// keep generating keys until a unique one is found
do {
key = new StringBuilder();
for (int i = 0; i < 6; i++) {
int r = (int)(Math.random() * SEED.length());
key.append(SEED.charAt(r));
}
} while (keyToURL.containsKey(key));
keyToURL.put(key.toString(), longUrl);
urlToKey.put(longUrl, key.toString());
return BASE + key;
}
public static String decode(String shortUrl) {
if (shortUrl == null || shortUrl.isEmpty()) {
return "";
}
String[] shortUrlSplits = shortUrl.split("/");
return keyToURL.get(shortUrlSplits[shortUrlSplits.length - 1]);
}
}
answer three
below is the tiny url solution in java, also this is the similar method in industry. In industry, most of shorten url service is by database, one auto increasing long number as primary key. whenever a long url need to be shorten, append to the database, and return the primary key number. (the database is very easy to distribute to multiple machine like HBase, or even you can use the raw file system to store data and improve performance by shard and replica).
Note, it’s meaningless to promise the same long url to be shorten as the same short url. if you do the promise and use something like hash to check existing, the benefit is must less than the cost.
Note: if you want the shorted url contains ‘0-9a-zA-Z’ instead of ‘0-9’, then you need to use 62 number system, not 10 number system(decimal) to convert the primary key number. like 123->‘123’ in decimal, 123->‘1Z’ in 62 number system (or ‘0001Z’ for align).
public class Codec {
List<String> urls = new ArrayList<String>();
// Encodes a URL to a shortened URL.
public String encode(String longUrl) {
urls.add(longUrl);
return String.valueOf(urls.size()-1);
}
// Decodes a shortened URL to its original URL.
public String decode(String shortUrl) {
int index = Integer.valueOf(shortUrl);
return (index<urls.size())?urls.get(index):"";
}
}
answer four
Use String build-in hashCode();
Map<Integer, String> map = new HashMap();
String host = "http://tinyurl.com/";
public String encode(String longUrl) {
int key = longUrl.hashCode();
map.put(key, longUrl);
return host+key;
}
public String decode(String shortUrl) {
int key = Integer.parseInt(shortUrl.replace(host,""));
return map.get(key);
}
answer five
Approach 1- Using simple counter
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/", "")));
}
}
Approach 2- using 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/", "")));
}
}
Approach 3- using random function
public class Codec {
Map<Integer, String> map = new HashMap<>();
Random r=new Random();
int key=r.nextInt(10000);
public String encode(String longUrl) {
while(map.containsKey(key))
key= r.nextInt(10000);
map.put(key,longUrl);
return "http://tinyurl.com/"+key;
}
public String decode(String shortUrl) {
return map.get(Integer.parseInt(shortUrl.replace("http://tinyurl.com/", "")));
}
}