LeetCode Weekly Contest 23

LeetCode Weekly Contest 23
[2017-03-12]

  1. Reverse String II
  2. Minimum Time Difference
  3. Construct Binary Tree from String
  4. Word Abbreviation

Reverse String II

Given a string and an integer k, you need to reverse the first k characters for every 2k characters counting from the start of the string. If there are less than k characters left, reverse all of them. If there are less than 2k but greater than or equal to k characters, then reverse the first k characters and left the other as original.
Example:

1
2
Input: s = "abcdefg", k = 2
Output: "bacdfeg"

Restrictions:

  1. The string consists of lower English letters only.
  2. Length of the given string and k will in the range [1, 10000]

code

1
2
3
4
5
6
7
8
class Solution {
public:
string reverseStr(string s, int k) {
for (int i = 0; i < s.size(); i += 2 * k)
reverse(s.begin() + i, s.begin() + min((int)s.size(), i + k));
return s;
}
};

Minimum Time Difference

Given a list of 24-hour clock time points in “Hour:Minutes” format, find the minimum minutes difference between any two time points in the list.

Example 1:

1
2
Input: ["23:59","00:00"]
Output: 1

Note:

  1. The number of time points in the given list is at least 2 and won’t exceed 20000.
  2. The input time is legal and ranges from 00:00 to 23:59.

code

O(n) Time O(1) Space

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public int findMinDifference(List<String> timePoints) {
boolean[] timeSeen = new boolean[1440];
for (String s : timePoints) {
int mins = Integer.parseInt(s.split(":")[0])*60 + Integer.parseInt(s.split(":")[1]);
if (timeSeen[mins]) return 0;
timeSeen[mins] = true;
}
Integer firstTimeSeen = null, prevTimeSeen = null, minDiff = Integer.MAX_VALUE;
for (int i=0;i<1440;i++) {
if (!timeSeen[i]) continue;
if (firstTimeSeen == null) {firstTimeSeen = i; prevTimeSeen = i;}
else {
minDiff = Math.min(minDiff, Math.min(i - prevTimeSeen, 1440 - i + prevTimeSeen));
prevTimeSeen = i;
}
}
minDiff = Math.min(minDiff, Math.min(prevTimeSeen - firstTimeSeen, 1440 - prevTimeSeen + firstTimeSeen));
return minDiff;
}

O(nlog(n)) Time O(1) Space:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public int findMinDifference(List<String> timePoints) {
Collections.sort(timePoints);
int minDiff = Integer.MAX_VALUE;
String prev = timePoints.get(timePoints.size()-1);
for (String s : timePoints) {
int prevMins = Integer.parseInt(prev.split(":")[0])*60 + Integer.parseInt(prev.split(":")[1]);
int curMins = Integer.parseInt(s.split(":")[0])*60 + Integer.parseInt(s.split(":")[1]);
int diff = curMins - prevMins;
if (diff < 0) diff += 1440;
minDiff = Math.min(minDiff, Math.min(diff, 1440 - diff));
prev = s;
}
return minDiff;
}


Construct Binary Tree from String

You need to construct a binary tree from a string consisting of parenthesis and integers.
The whole input represents a binary tree. It contains an integer followed by zero, one or two pairs of parenthesis. The integer represents the root’s value and a pair of parenthesis contains a child binary tree with the same structure.
You always start to construct the left child node of the parent first if it exists.

Example:

1
2
3
4
5
6
7
8
Input: "4(2(3)(1))(6(5))"
Output: return the tree root node representing the following tree:
4
/ \
2 6
/ \ /
3 1 5

Note:

  1. There will only be ‘(‘, ‘)’, ‘-‘ and ‘0’ ~ ‘9’ in the input string.

code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class Solution {
public:
TreeNode* str2tree(string s) {
int i = 0;
return s.size() == 0 ? nullptr : build(s, i);
}
private:
TreeNode* build(string& s, int& i) {
int start = i;
if (s[i] == '-') {
i++;
}
while (isdigit(s[i])) {
i++;
}
int num = stoi(s.substr(start, i - start));
TreeNode* node = new TreeNode(num);
if (s[i] == '(') {
node->left = build(s, ++i);
i++; // )
}
if (s[i] == '(') {
node->right = build(s, ++i);
i++; // )
}
return node;
}
};

Word Abbreviation

Given an array of n distinct non-empty strings, you need to generate minimal possible abbreviations for every word following rules below.

  1. Begin with the first character and then the number of characters abbreviated, which followed by the last character.
  2. If there are any conflict, that is more than one words share the same abbreviation, a longer prefix is used instead of only the first character until making the map from word to abbreviation become unique. In other words, a final abbreviation cannot map to more than one original words.
  3. If the abbreviation doesn’t make the word shorter, then keep it as original.

Example:

1
2
Input: ["like", "god", "internal", "me", "internet", "interval", "intension", "face", "intrusion"]
Output: ["l2e","god","internal","me","i6t","interval","inte4n","f2e","intr4n"]

Note:

  1. Both n and the length of each word will not exceed 400.
  2. The length of each word is greater than 1.
  3. The words consist of lowercase English letters only.
  4. The return answers should be in the same order as the original array.

    code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
public class Solution {
public List<String> wordsAbbreviation(List<String> dict) {
Map<String, String> wordToAbbr = new HashMap<>();
Map<Integer, List<String>> groups = new HashMap<>();
// Try to group words by their length. Because no point to compare words with different length.
// Also no point to look at words with length < 4.
for (String word : dict) {
int len = word.length();
if (len < 4) {
wordToAbbr.put(word, word);
}
else {
List<String> g = groups.getOrDefault(len, new ArrayList<String>());
g.add(word);
groups.put(len, g);
}
}
// For each group of words with same length, generate a result HashMap.
for (int len : groups.keySet()) {
Map<String, String> res = getAbbr(groups.get(len));
for (String word : res.keySet()) {
wordToAbbr.put(word, res.get(word));
}
}
// Generate the result list
List<String> result = new ArrayList<>();
for (String word : dict) {
result.add(wordToAbbr.get(word));
}
return result;
}
private Map<String, String> getAbbr(List<String> words) {
Map<String, String> res = new HashMap<>();
int len = words.get(0).length();
// Try to abbreviate a word from index 1 to len - 2
for (int i = 1; i < len - 2; i++) {
Map<String, String> abbrToWord = new HashMap<>();
for (String s : words) {
if (res.containsKey(s)) continue;
// Generate the current abbreviation
String abbr = s.substring(0, i) + (len - 1 - i) + s.charAt(len - 1);
// Tick: use reversed abbreviation to word map to check if there is any duplicated abbreviation
if (!abbrToWord.containsKey(abbr)) {
abbrToWord.put(abbr, s);
}
else {
abbrToWord.put(abbr, "");
}
}
// Add unique abbreviations find during this round to result HashMap
for (String abbr : abbrToWord.keySet()) {
String s = abbrToWord.get(abbr);
// Not a unique abbreviation
if (s.length() == 0) continue;
res.put(s, abbr);
}
}
// Add all words that can't be shortened.
for (String s : words) {
if (!res.containsKey(s)) {
res.put(s, s);
}
}
return res;
}
}