Given a string, we can "shift" each of its letter to its successive letter, for example: "abc" -> "bcd". We can keep "shifting" which forms the sequence:

"abc" -> "bcd" -> ... -> "xyz"

Given a list of strings which contains only lowercase alphabets, group all strings that belong to the same shifting sequence.

For example, given: ["abc", "bcd", "acef", "xyz", "az", "ba", "a", "z"]
Return:

[
["abc","bcd","xyz"],
["az","ba"],
["acef"],
["a","z"]
]

Note: For the return value, each inner list's elements must follow the lexicographic order.

 

这道题让我们重组偏移字符串,所谓偏移字符串,就是一个字符串的每个字符按照字母顺序表偏移相同量得到的另一个字符串,两者互为偏移字符串,注意相同字符串是偏移字符串的一种特殊情况,因为偏移量为0。现在给了一堆长度不同的字符串,让把互为偏移字符串的归并到一起,博主最开始想的是建立字符度和该长度的所有偏移字符串的映射,但是很明显的错误是相同长度的不一定都是偏移字符串,比如 'ab' 和 'ba',所以只能用 HashMap 来建立一个字符串和所有和此字符串是偏移字符串的集合之间的映射,由于题目要求结果是按字母顺序的,所以用 multiset 来保存结果,一来可以保存重复字符串,二来可以自动排序。然后博主还写了一个判断二个字符串是否互为偏移字符串的函数,注意在比较两个字母距离时采用了加 26,再对 26 取余的 trick。遍历给定字符串集,对于遍历到的字符串,再遍历哈希表,和每个关键字调用 isShifted 函数来比较,如果互为偏移字符串,则加入其对应的字符串集,并标记 flag,最后遍历完 HashMap,没有跟任何关键字互为偏移,那么就新建一个映射,最后要做的就是把 multiset 转换为 vector 即可,参见代码如下:

解法一:

// Correct but complicated
class Solution {
public:
vector<vector<string>> groupStrings(vector<string>& strings) {
vector<vector<string> > res;
unordered_map<string, multiset<string>> m;
for (auto a : strings) {
bool b = false;
for (auto it = m.begin(); it != m.end(); ++it) {
if (isShifted(it->first, a)) {
it->second.insert(a);
b = true;
}
}
if (!b) m[a] = {a};
}
for (auto it = m.begin(); it != m.end(); ++it) {
res.push_back(vector<string>(it->second.begin(), it->second.end()));
}
return res;
}
bool isShifted(string s1, string s2) {
if (s1.size() != s2.size()) return false;
int diff = (s1[] + - s2[]) % ;
for (int i = ; i < s1.size(); ++i) {
if ((s1[i] + - s2[i]) % != diff) return false;
}
return true;
}
};

上面那个方法挺复杂的,其实有更好的方法,网友的智慧无穷啊,上面那个方法的不高效之处在于对于每个遍历到的字符串,都要和 HashMap 中所有的关键字都比较一次,而其实我们可以更加巧妙的利用偏移字符串的特点,那就是字符串的每个字母和首字符的相对距离都是相等的,比如 abc 和 efg 互为偏移,对于 abc 来说,b和a的距离是1,c和a的距离是2,对于 efg 来说,f和e的距离是1,g和e的距离是2。再来看一个例子,az 和 yx,z和a的距离是 25,x和y的距离也是 25 (直接相减是 -1,这就是要加 26 然后取余的原因),那么这样的话,所有互为偏移的字符串都有个 unique 的距离差,根据这个来建立映射就可以很好的进行单词分组了,这个思路真实太赞了,参见代码如下:

解法二:

class Solution {
public:
vector<vector<string>> groupStrings(vector<string>& strings) {
vector<vector<string> > res;
unordered_map<string, multiset<string>> m;
for (auto a : strings) {
string t = "";
for (char c : a) {
t += to_string((c + - a[]) % ) + ",";
}
m[t].insert(a);
}
for (auto it = m.begin(); it != m.end(); ++it) {
res.push_back(vector<string>(it->second.begin(), it->second.end()));
}
return res;
}
};

Github 同步地址:

https://github.com/grandyang/leetcode/issues/249

类似题目:

Group Anagrams

参考资料:

https://leetcode.com/problems/group-shifted-strings/

https://leetcode.com/problems/group-shifted-strings/discuss/67442/My-Concise-JAVA-Solution

https://leetcode.com/problems/group-shifted-strings/discuss/67451/4ms-Easy-C%2B%2B-Solution-with-Explanations

https://leetcode.com/problems/group-shifted-strings/discuss/67452/Concise-10-lines-JAVA-Solution-with-explanation

LeetCode All in One 题目讲解汇总(持续更新中...)

[LeetCode] Group Shifted Strings 群组偏移字符串的更多相关文章

  1. [Swift]LeetCode249.群组偏移字符串 $ Group Shifted Strings

    Given a string, we can "shift" each of its letter to its successive letter, for example: & ...

  2. LeetCode – Group Shifted Strings

    Given a string, we can "shift" each of its letter to its successive letter, for example: & ...

  3. [Locked] Group Shifted Strings

    Group Shifted Strings Given a string, we can "shift" each of its letter to its successive ...

  4. LeetCode 249. Group Shifted Strings (群组移位字符串)$

    Given a string, we can "shift" each of its letter to its successive letter, for example: & ...

  5. [LeetCode] 249. Group Shifted Strings 分组偏移字符串

    Given a string, we can "shift" each of its letter to its successive letter, for example: & ...

  6. [LeetCode#249] Group Shifted Strings

    Problem: Given a string, we can "shift" each of its letter to its successive letter, for e ...

  7. 249. Group Shifted Strings把迁移后相同的字符串集合起来

    [抄题]: Given a string, we can "shift" each of its letter to its successive letter, for exam ...

  8. Group Shifted Strings -- LeetCode

    Given a string, we can "shift" each of its letter to its successive letter, for example: & ...

  9. Group Shifted Strings

    Given a string, we can "shift" each of its letter to its successive letter, for example: & ...

随机推荐

  1. shell脚本规划化模板

    shell脚本规划化模板 Linux运维过程中,shell脚本是不可缺少的工具,但是每个运维人员编程的习惯都不一样,很多时候就是实现某个功能,写出来的脚本都是烂七八糟的.脚本必须规范化,应该从以后几个 ...

  2. python之最强王者(2)——python基础语法

    背景介绍:由于本人一直做java开发,也是从txt开始写hello,world,使用javac命令编译,一直到使用myeclipse,其中的道理和辛酸都懂(请容许我擦干眼角的泪水),所以对于pytho ...

  3. Java--String 和StringBuilder、StringBuffer 的区别?

    1.String是只读字符串,引用的字符串内容是无法改变的. 2.StringBuffer和StringBuilder的字符串对象可以直接进行修改. 3.StringBuilder没有被synchro ...

  4. Bootstrap 之 Carousel

    Bootstrap 轮播(Carousel)插件是一种灵活的响应式的向站点添加滑块的方式.除此之外,内容也是足够灵活的,可以是图像.内嵌框架.视频或者其他您想要放置的任何类型的内容. 如果您想要单独引 ...

  5. 你必须收藏的Github技巧

    一秒钟把Github项目变成前端网站 GitHub Pages大家可能都知道,常用的做法,是建立一个gh-pages的分支,通过setting里的设置的GitHub Pages模块可以自动创建该项目的 ...

  6. ES5概述(ECMAScript262/5.1)

    ES5概述(ECMAScript262/5.1) 本文参考:ES5概述 ECMAScript 是基于对象的: 基本语言和宿主设施都由对象提供,ECMAScript 程序是一组可通信的对象.ECMASc ...

  7. js实现无缝循环滚动

    <!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. Atitit ati licenseService    设计原理

    Atitit ati licenseService    设计原理 C:\0workspace\AtiPlatf\src_atibrow\com\attilax\license\LicenseX.ja ...

  9. webpack-dev-server轻量级js高速打包、热部署服务器

    webpack是一个打包web项目的工具 ,可以实现css,js,less,cass,html的混淆加密,minify,结合webpack-dev-server热部署,非常方便前端页面和Nodejs的 ...

  10. 9套Android实战经典项目资料分享给大家

    通过项目学习收获更大. 1.基于Android平台实战爱短信项目 下载地址:http://pan.baidu.com/s/1hr8CEry 2.Android平台实战CRM客户关系管理(AChartE ...