249. Group Shifted Strings
题目:
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.
链接: http://leetcode.com/problems/group-shifted-strings/
题解:
一道简单题,我又写得巨长...水平太有限了,唉。主要是数据结构选了一个Map<Integer, Map<String, List<String>>>,先以String长度为key,再以单词为key,List<String>为value。 其实可以不用这么麻烦, 就用Map<String,List<String>>就可以了。遍历keySet()的时候,只要长度不一样,continue就行了。时间复杂度还是一样的。 假设单词长度有限的情况下,还是O(n2)。 二刷再简化..........这句话说了几百遍。二刷再简化吧!
Time Complexity - O(n2), Space Complexity - O(n)。
public class Solution {
public List<List<String>> groupStrings(String[] strings) {
List<List<String>> res = new ArrayList<>();
if(strings == null || strings.length == 0)
return res;
Arrays.sort(strings);
Map<Integer, Map<String, List<String>>> map = new HashMap<>();
for(int i = 0; i < strings.length; i++) {
String s = strings[i];
int len = s.length();
if(!map.containsKey(len)) {
Map<String, List<String>> tmpMap = new HashMap<>();
tmpMap.put(s, new ArrayList<>(Arrays.asList(s)));
map.put(len, tmpMap);
} else {
Map<String, List<String>> tmpMap = map.get(len);
boolean hasSequence = false;
outerloop:
for(String t : tmpMap.keySet()) {
for(int k = 1; k < len; k++) {
int curDistance = (int)(s.charAt(k) - t.charAt(k));
int lastDistance = (int)(s.charAt(k - 1) - t.charAt(k - 1));
curDistance = curDistance >= 0 ? curDistance : curDistance + 26;
lastDistance = lastDistance >= 0 ? lastDistance : lastDistance + 26;
if(curDistance != lastDistance)
continue outerloop;
}
tmpMap.get(t).add(s);
hasSequence = true;
break;
}
if(!hasSequence) {
tmpMap.put(s, new ArrayList<>(Arrays.asList(s)));
}
}
}
for(int i : map.keySet()) {
Map<String, List<String>> tmpMap = map.get(i);
for(String s : tmpMap.keySet()) {
res.add(map.get(i).get(s));
}
}
return res;
}
}
二刷:
二刷就好一些。之前写得比较乱也不容易懂,下面来分析二刷的想法。
- 主要是利用和求anagram一样的方法,利用HashMap来保存能group到一起的单词
- 对于能group到一起的每个单词来说,他们都会有一个base case,每个单词都是从这个base case shift出去的, 比如 abc, bcd, cde一类的,我们可以把abc认定为base case,那么所有base case为abc的单词,我们就可以group到一起
- 了解了原理,接下来我们就可以操作实现了,首先我们有一个HashMap<String,List<String>>, 这里的key是base case String, 比如abc, ab, a一类的, 而value List<String>就是可以被放入结果集中的List
- 我们遍历给定的数组Strings, 对于每一个单词s,
- 我们求出它的base case string
- 这里另外写了一个球base case string的方法getBaseStr
- 我们假定所有的base case string均以'a'为第一个字母
- 求出第一个字母被shift的长度lenShifted = s.charAt(0) - 'a', 并且建立一个StringBuilder用来保存结果
- 接下来对于string s中的每一个字母c,我们计算他在被移动lenShifted个长度之前的字母是什么
- 我们可以用c - 'a'求出c到'a'的距离, 再减去这个lenShifted,就得到了当前这个字母究竟被shift了多少个单位curShifted
- 之后处理一下特殊情况,当这个curShifted < 0的时候,我们要加上26,把它重新映射到26个小写字母里
- 最后求出c = char('a' + curShifted),这时更新后的c就是 shift之前的base char
- 我们把这个base char存入StringBuilder里,接着计算下一个字符。 (这里也可以使用stefan pochmann的写法大大简化代码)
- 最后返回sb.toString()就是我们要求的base case string
- 得到base case string把单词按照base case string存入到hashmap里
- 我们求出它的base case string
- 遍历完毕以后,我们还要对HashMap中的每个group进行排序
- 最后利用hashMap的结果集合values生成最终结果, 即 res = new ArrayList<List<String>>(map.values());
Java:
Time Complexity - O(nlogn), Space Complexity - O(n)。
public class Solution {
public List<List<String>> groupStrings(String[] strings) {
List<List<String>> res = new ArrayList<>();
if (strings == null || strings.length == 0) {
return res;
}
Map<String, List<String>> map = new HashMap<>();
for (String s : strings) {
String base = getBaseStr(s);
if (!map.containsKey(base)) {
map.put(base, new ArrayList<>());
}
map.get(base).add(s);
}
for (String s : map.keySet()) {
Collections.sort(map.get(s));
}
res = new ArrayList<List<String>>(map.values());
return res;
}
private String getBaseStr(String s) {
if (s == null || s.length() == 0) {
return s;
}
StringBuilder sb = new StringBuilder();
int lenShifted = s.charAt(0) - 'a';
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
int curShifted = c - 'a' - lenShifted;
if (curShifted < 0) {
curShifted += 26;
}
c = (char)('a' + curShifted);
sb.append(c);
}
return sb.toString();
}
}
Reference:
https://leetcode.com/discuss/50358/my-concise-java-solution
https://leetcode.com/discuss/69783/concise-10-lines-java-solution-with-explanation
https://leetcode.com/discuss/67240/around-13-lines-code-in-java
https://leetcode.com/discuss/64979/simple-solution-in-java-with-detailed-explaination
https://leetcode.com/discuss/64751/cannot-pass-tests-seems-nothing-wrong-for-the-custom-testcase
https://leetcode.com/discuss/58003/java-solution-with-separate-shiftstr-function
https://leetcode.com/discuss/53166/4ms-c-solution
https://leetcode.com/discuss/52627/python-easy-to-understand-solution-with-comments
https://leetcode.com/discuss/50582/4ms-c-solution
https://leetcode.com/discuss/50557/4ms-easy-c-solution-with-explanations
https://leetcode.com/discuss/50416/1-4-lines-in-java
https://leetcode.com/discuss/50163/1-4-lines-ruby-and-python
249. Group Shifted Strings的更多相关文章
- [LeetCode#249] Group Shifted Strings
Problem: Given a string, we can "shift" each of its letter to its successive letter, for e ...
- 249. Group Shifted Strings把迁移后相同的字符串集合起来
[抄题]: Given a string, we can "shift" each of its letter to its successive letter, for exam ...
- LeetCode 249. Group Shifted Strings (群组移位字符串)$
Given a string, we can "shift" each of its letter to its successive letter, for example: & ...
- [LeetCode] 249. Group Shifted Strings 分组偏移字符串
Given a string, we can "shift" each of its letter to its successive letter, for example: & ...
- [Locked] Group Shifted Strings
Group Shifted Strings Given a string, we can "shift" each of its letter to its successive ...
- [LeetCode] Group Shifted Strings 群组偏移字符串
Given a string, we can "shift" each of its letter to its successive letter, for example: & ...
- Group Shifted Strings
Given a string, we can "shift" each of its letter to its successive letter, for example: & ...
- [Swift]LeetCode249.群组偏移字符串 $ Group Shifted Strings
Given a string, we can "shift" each of its letter to its successive letter, for example: & ...
- LeetCode – Group Shifted Strings
Given a string, we can "shift" each of its letter to its successive letter, for example: & ...
随机推荐
- TDirectory.CreateDirectory 完整、严谨的创建一个目录
描述:创建一个目录,不包含多级目录(多级目录使用System.SysUtils.ForceDirectories,Vcl.FileCtrl.ForceDirectories已过时) procedure ...
- 【转】Python的XML-RPC简介
编写客户端提交数据到服务器处理是程序员最常碰到的几个问题之一.各种不同的语言对此都有相应的解决方案.比如Unix下,C程序员们可以用SUNRPC,Java程序员则使用RMI来处理.大多数语言还都可以使 ...
- Azure IaaS for IT Pros Online Event 总结
微软一个为期4天的一个有关于Azure的介绍,主要总结了些Azure现有的技术以及将会推出东西 主题链接 http://channel9.msdn.com/Events/Microsoft-Azure ...
- .NET特性-Attribute
两篇文章有助于学习Attribute特性的概念. http://blog.csdn.net/byondocean/article/details/6802111 http://www.cnblogs. ...
- Sybase ASE报错:server Error: 8242, Severity: 16, State: 1
昨天上午,同事反映某系统在执行存储过程的过程中报错了,报错的信息异常如下: 05:00000:00009:2014/06/09 15:45:30.34 server Error: 8242, Seve ...
- linux内核中的get_user和put_user
linux内核中的get_user和put_user 在 内核空间和用户空间交换数据时,get_user和put_user是两个两用的函数.相对于copy_to_user和 copy_from_use ...
- iTween基础之Scale(缩放大小)
一.基础介绍:二.基础属性 原文地址:http://blog.csdn.net/dingkun520wy/article/details/50684392 一.基础介绍 ScaleTo:改变游戏对象的 ...
- c# 重载运算符(+-|&)和扩展方法
通常我们需要对class的相加,相减,相乘 等重载以适应需求, 如caml查询的时候,我们可以定义一个caml类,然后来操作这些查询. 首先,我们定义一个class为Test public class ...
- 输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。
// test20.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include<iostream> #include< ...
- C# mongodb [上]
概述 MongoDB是一个高性能,开源,无模式的文档型数据库,使用C++开发.是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的.他支持的数据结构非常松散,是 ...