LeetCode 249: Group Shifted Strings (Hash Map / String Normalization)
LeetCode 249Hash MapStringToday we solve LeetCode 249 - Group Shifted Strings.
Source: https://leetcode.com/problems/group-shifted-strings/
English
Problem Summary
Group strings where each can be shifted letter-by-letter with wraparound (z to a) to match another string.
Key Insight
Strings are in the same group if adjacent character differences modulo 26 are identical.
Complexity
Time: O(totalChars), Space: O(totalChars).
Reference Implementations (Java / Go / C++ / Python / JavaScript)
None中文
题目概述
把可以通过每个字符统一平移(含 z→a 回环)互相得到的字符串分到同一组。
核心思路
同组字符串的相邻字符差值序列(mod 26)完全一致,用它做哈希键即可。
复杂度分析
时间复杂度 O(总字符数),空间复杂度 O(总字符数)。
多语言参考实现(Java / Go / C++ / Python / JavaScript)
class Solution {
public List<List<String>> groupStrings(String[] strings) {
Map<String, List<String>> mp = new HashMap<>();
for (String s : strings) mp.computeIfAbsent(key(s), k -> new ArrayList<>()).add(s);
return new ArrayList<>(mp.values());
}
private String key(String s) {
if (s.length() == 1) return "single";
StringBuilder sb = new StringBuilder();
for (int i = 1; i < s.length(); i++) {
int d = (s.charAt(i) - s.charAt(i - 1) + 26) % 26;
sb.append(d).append('#');
}
return sb.toString();
}
}func groupStrings(strings []string) [][]string {
mp := map[string][]string{}
for _, s := range strings {
mp[key(s)] = append(mp[key(s)], s)
}
ans := make([][]string, 0, len(mp))
for _, v := range mp { ans = append(ans, v) }
return ans
}
func key(s string) string {
if len(s) == 1 { return "single" }
b := strings.Builder{}
for i := 1; i < len(s); i++ {
d := (int(s[i]) - int(s[i-1]) + 26) % 26
b.WriteString(strconv.Itoa(d)); b.WriteByte('#')
}
return b.String()
}class Solution {
public:
vector<vector<string>> groupStrings(vector<string>& strings) {
unordered_map<string, vector<string>> mp;
for (auto &s : strings) mp[key(s)].push_back(s);
vector<vector<string>> ans;
for (auto &p : mp) ans.push_back(move(p.second));
return ans;
}
string key(const string& s) {
if (s.size() == 1) return "single";
string k;
for (int i = 1; i < (int)s.size(); ++i) {
int d = (s[i] - s[i-1] + 26) % 26;
k += to_string(d) + "#";
}
return k;
}
};class Solution:
def groupStrings(self, strings: List[str]) -> List[List[str]]:
groups = defaultdict(list)
for s in strings:
groups[self.key(s)].append(s)
return list(groups.values())
def key(self, s: str) -> str:
if len(s) == 1:
return "single"
return "#".join(str((ord(s[i]) - ord(s[i-1])) % 26) for i in range(1, len(s)))function groupStrings(strings) {
const mp = new Map();
for (const s of strings) {
const k = key(s);
if (!mp.has(k)) mp.set(k, []);
mp.get(k).push(s);
}
return [...mp.values()];
}
function key(s) {
if (s.length === 1) return 'single';
const arr = [];
for (let i = 1; i < s.length; i++) arr.push((s.charCodeAt(i) - s.charCodeAt(i - 1) + 26) % 26);
return arr.join('#');
}
Comments