"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.
[分析]
思路1:第一次按长度分组,然后在第一次的各分组中按照是否属于同一shifted sequence再次分组。如何判断是否属于同一shifted sequence呢? 两个字符串x 和 y,若对于任意i,满足y[i] - x[i] = y[0] - x[0], 注意要处理类似"az", "yx"这种情况。代码很长,实现也容易出错。
思路2:对于输入数组中的每个字符串,将其“归零”,即求出该字符串对应的shifted squence中的第一个字符串(a为起始字符)。维护一个哈希表,key为各group的“零值”,value是输入数组中属于该group的字符串。 参考 https://leetcode.com/discuss/50358/my-concise-java-solution 佩服作者~
public class Solution { // Method 2 public List<List<String>> groupStrings(String[] strings) { List<List<String>> ret = new ArrayList<List<String>>(); if (strings == null) return ret; HashMap<String, List<String>> map = new HashMap<String, List<String>>(); for (String s : strings) { int offset = s.charAt(0) - 'a'; String key = "a"; for (int i = 1; i < s.length(); i++) { char c = (char)(s.charAt(i) - offset); if (c < 'a') c += 26; key += c; } if (!map.containsKey(key)) { map.put(key, new ArrayList<String>()); } map.get(key).add(s); } for (List<String> list : map.values()) { Collections.sort(list); ret.add(list); } return ret; } // Method 1 public List<List<String>> groupStrings1(String[] strings) { List<List<String>> ret = new ArrayList<List<String>>(); if (strings == null) return ret; // group by length HashMap<Integer, List<String>> map = new HashMap<Integer, List<String>>(); for (String s : strings) { if (!map.containsKey(s.length())) { map.put(s.length(), new ArrayList<String>()); } map.get(s.length()).add(s); } // in each length group, group shifted strings HashMap<Integer, List<String>> map2 = new HashMap<Integer, List<String>>(); HashMap<String, List<String>> shiftedMap = new HashMap<String, List<String>>(); for (List<String> list : map.values()) { int i = 0; while (i < list.size()) { String curr = list.get(i++); int currLen = curr.length(); if (!map2.containsKey(currLen)) { map2.put(currLen, new ArrayList<String>()); map2.get(currLen).add(curr); shiftedMap.put(curr, new ArrayList<String>()); shiftedMap.get(curr).add(curr); } else { List<String> sameLenDiffGroupBase = map2.get(currLen); boolean findBuddy = false; for (String base : sameLenDiffGroupBase) { int diff = curr.charAt(0) - base.charAt(0); if (diff < 0) diff += 26; int j = 1; for (; j < currLen; j++) { if ((base.charAt(j) - 'a' + diff) % 26 + 'a' != curr.charAt(j)) break; } if (j == currLen) { shiftedMap.get(base).add(curr); // find the group which curr belong to findBuddy = true; break; } } if (!findBuddy) {//curr will start a new group map2.get(currLen).add(curr); shiftedMap.put(curr, new ArrayList<String>()); shiftedMap.get(curr).add(curr); } } } } // put each group in shiftedMap into result for (List<String> list : shiftedMap.values()) { Collections.sort(list); ret.add(list); } return ret; } }