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 non-empty strings which contains only lowercase alphabets, group all strings that belong to the same shifting sequence.
Example:
Input: ["abc", "bcd", "acef", "xyz", "az", "ba", "a", "z"],
Output:
[
["abc","bcd","xyz"],
["az","ba"],
["acef"],
["a","z"]
]
移位字符串分组。
给定一个字符串,对该字符串可以进行 “移位” 的操作,也就是将字符串中每个字母都变为其在字母表中后续的字母,比如:"abc" -> "bcd"。这样,我们可以持续进行 “移位” 操作,从而生成如下移位序列:
"abc" -> "bcd" -> ... -> "xyz"
给定一个包含仅小写字母字符串的列表,将该列表中所有满足 “移位” 操作规律的组合进行分组并返回。来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/group-shifted-strings
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题意跟49题anagram非常类似,唯一多一个条件是同组的单词可以是经过移位的。那么input里面能够被分到一组的字符串有什么共性呢,还是回到abc和bcd的例子,因为在abc中,后一个字母跟前一个字母之间的差距是1,所以他们同组。另外再看一个例子,为什么az和ba也能同组呢?因为z - a = 25, a - b = -1。但是由于一共只有26个字母,所以由b到a,实际中间只shift了25位。处理这种情形的时候,如果遇到负数,只需要加26即可。
思路依然是创建一个hashmap,hashmap的key是某一个字符串,value是一个list,list里面存的是来自input的字符串。key是怎么得到呢?key是每两个字符串之间的差值(用逗号隔开)。这样做,既能抓到字母之间的差值,又能算好每个单词里面到底有几个字母。代码中的getKey函数实现了这个目标,最后输出的key长这样。
这个题目不难,但是怎么处理key的部分需要多练。
时间O(m * n) - m个单词 * 单词平均长度
空间O(n) - hashmap
Java实现
1 class Solution { 2 public List<List<String>> groupStrings(String[] strings) { 3 List<List<String>> res = new ArrayList<>(); 4 HashMap<String, List<String>> map = new HashMap<>(); 5 for (String str : strings) { 6 String key = getKey(str); 7 List<String> list = map.getOrDefault(key, new ArrayList<>()); 8 list.add(str); 9 map.put(key, list); 10 } 11 return new ArrayList<>(map.values()); 12 } 13 14 private String getKey(String s) { 15 char[] chars = s.toCharArray(); 16 String key = ""; 17 for (int i = 1; i < s.length(); i++) { 18 int diff = chars[i] - chars[i - 1]; 19 key += diff < 0 ? diff + 26 : diff; 20 key += ","; 21 } 22 return key; 23 } 24 }