Skip to content

Commit 34b5d07

Browse files
refactor 535
1 parent 41f4661 commit 34b5d07

File tree

1 file changed

+110
-9
lines changed
  • src/main/java/com/fishercoder/solutions

1 file changed

+110
-9
lines changed

src/main/java/com/fishercoder/solutions/_535.java

Lines changed: 110 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@
22

33
import java.util.HashMap;
44
import java.util.Map;
5+
import java.util.Random;
56

67
/**
8+
* 535. Encode and Decode TinyURL
9+
*
710
* TinyURL is a URL shortening service where you enter a URL such as https://leetcode.com/problems/design-tinyurl
811
* and it returns a short URL such as http://tinyurl.com/4e9iAk.
912
* Design the encode and decode methods for the TinyURL service.
@@ -12,23 +15,121 @@
1215
1316
Note: Do not use class member/global/static variables to store states. Your encode and decode algorithms should be stateless.
1417
*/
18+
1519
public class _535 {
16-
public class Codec {
17-
Map<String, Long> map = new HashMap<>();
18-
Long maxValue = 0L;
19-
Map<Long, String> reverseMap = new HashMap<>();
20+
21+
public static class Solution1 {
22+
/**
23+
* Simple counter approach
24+
* Analysis:
25+
* The range of URLs that can be decoded is limited by the range of Integer.
26+
* If excessively large number of URLs have to be encoded, after the range of Integer is exceeded,
27+
* integer overflow could lead to overwriting previous URL's encodings.
28+
* The length of the URL isn't necessary shorter than incoming URL.
29+
* One potential security issue with this problem is that it's very easy to predict the next code generated,
30+
* since this pattern is very easy to be detected.
31+
*/
32+
public class Codec {
33+
int i = 0;
34+
Map<Integer, String> map = new HashMap();
35+
public static final String PREFIX = "http://tinyurl/";
36+
37+
public String encode(String longUrl) {
38+
map.put(i, longUrl);
39+
return PREFIX + i++;
40+
}
41+
42+
public String decode(String shortUrl) {
43+
return map.get(Integer.parseInt(shortUrl.substring(PREFIX.length())));
44+
}
45+
}
46+
}
47+
48+
public static class Solution2 {
49+
/**
50+
* Use Java built-in HashCode
51+
* Analysis:
52+
* hashCode() does NOT generate unique codes for different strings, collision might happen.
53+
* As the number of URLs increase, the probability of getting collision increases which leads to failure.
54+
*/
55+
public class Codec {
56+
Map<Integer, String> map = new HashMap<>();
57+
public static final String PREFIX = "http://tinyurl/";
58+
59+
// Encodes a URL to a shortened URL.
60+
public String encode(String longUrl) {
61+
/**I don't need to create a local variable to cache longUrl.hashCode()
62+
* since Java's String cache it already. :) Look at its source code.*/
63+
map.put(longUrl.hashCode(), longUrl);
64+
return PREFIX + longUrl.hashCode();
65+
}
66+
67+
// Decodes a shortened URL to its original URL.
68+
public String decode(String shortUrl) {
69+
return map.get(Integer.parseInt(shortUrl.substring(PREFIX.length())));
70+
}
71+
}
72+
}
73+
74+
public static class Solution3 {
75+
/**Use a random number*/
76+
Map<Integer, String> map = new HashMap<>();
77+
Random random = new Random();
78+
public static final String PREFIX = "http://tinyurl/";
2079

2180
// Encodes a URL to a shortened URL.
2281
public String encode(String longUrl) {
23-
maxValue++;
24-
map.put(longUrl, maxValue);
25-
reverseMap.put(maxValue, longUrl);
26-
return String.valueOf(maxValue);
82+
int num = random.nextInt(Integer.MAX_VALUE);
83+
while (map.containsKey(num)) {
84+
num = random.nextInt(Integer.MAX_VALUE);
85+
}
86+
map.put(num, longUrl);
87+
return PREFIX + num;
88+
}
89+
90+
// Decodes a shortened URL to its original URL.
91+
public String decode(String shortUrl) {
92+
return map.get(Integer.parseInt(shortUrl.substring(PREFIX.length())));
93+
}
94+
}
95+
96+
public static class Solution4 {
97+
/**
98+
* Use a random but fixed length encoding
99+
* Analysis:
100+
* 1. This is the most optimal solution so far.
101+
* 2. The number of URLs that can be encoded can be as big as Math.pow((10 + 26*2), FIXED_LENGTH)
102+
* 3. The length of the shortened URL is fixed at a certain length, which could be a significant reduce for large URLs
103+
* 4. The performance of this scheme is pretty good, due to much smaller probability of encountering collision
104+
* 5. Predicting pattern/encoding isn't possible in this case since random numbers are used.
105+
*/
106+
Map<String, String> map = new HashMap<>();
107+
public static final String PREFIX = "http://tinyurl/";
108+
public static final int FIXED_LENGTH = 7;
109+
Random random = new Random();
110+
String alphabet = "0123456789abcdefghijklmnopgrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
111+
112+
// Encodes a URL to a shortened URL.
113+
public String encode(String longUrl) {
114+
String shortKey = getRandomFixedLengthKey();
115+
while (map.containsKey(shortKey)) {
116+
shortKey = getRandomFixedLengthKey();
117+
}
118+
map.put(shortKey, longUrl);
119+
return PREFIX + shortKey;
120+
}
121+
122+
private String getRandomFixedLengthKey() {
123+
StringBuilder stringBuilder = new StringBuilder();
124+
for (int i = 0; i < FIXED_LENGTH; i++) {
125+
stringBuilder.append(alphabet.charAt(random.nextInt(alphabet.length())));
126+
}
127+
return stringBuilder.toString();
27128
}
28129

29130
// Decodes a shortened URL to its original URL.
30131
public String decode(String shortUrl) {
31-
return String.valueOf(reverseMap.get(Long.valueOf(shortUrl)));
132+
return map.get(shortUrl.substring(PREFIX.length()));
32133
}
33134
}
34135
}

0 commit comments

Comments
 (0)