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"], A solution is:

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

Tips:

O(n2)

每个字母和首字母的相对距离都是相等的,比如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的距离差,我们根据这个来建立映射就可以很好的进行单词分组了

Code:

public class Solution {
    public List<List<String>> groupStrings(String[] strings) {
        List<List<String>> result = new ArrayList<>();
        Map<String, List<String>> map = new HashMap<>();
        for(String s: strings){
            String key = getBitMap(s);
            if(!map.containsKey(key))
                map.put(key, new ArrayList<String>());
            map.get(key).add(s);
        }
        for(String key: map.keySet()){
            List<String> list = map.get(key);
            //Collections.sort(list);
            result.add(list);
        }
        return result;
    }
    private String getBitMap(String s){
        int[] arr = new int[s.length()];
        arr[0] = 0;
        for(int i = 1; i < s.length(); i++){
            arr[i] = s.charAt(i)-s.charAt(0) < 0? 
                     ((s.charAt(i)-s.charAt(0))%26 + 26): (s.charAt(i)-s.charAt(0));
        }
        return Arrays.toString(arr);
    }
}

results matching ""

    No results matching ""