Given a list of strings, group the strings that are equivalent when rotated. For example, the input
["abc", "bca", "cab", "xyz", "yzx", "cba", "aaaa"]
should return the groups:
{["abc", "bca", "cab"], ["xyz, "yzx"], ["cba"], ["aaaa"]}
The order of the strings or the groups for the result does not matter.
{["cba"], ["xyz, "yzx"], ["bca", "abc", "cab"], ["aaaa"]}
is an acceptable solution too.
Knew how to find if one string is a rotated version of the other but couldn't piece out how to put in the common group. Another approach which I preferred is to generate hash of string and seems that is a wrong approach. Any inputs on how to approach for this problem?
Skeleton:
public class GroupRotatedStrings
{
public static void main(String[] args)
{
List<String> input = Arrays.asList("abc", "bca", "cab", "xyz", "yzx", "cba", "aaaa");
List<List<String>> groups = groupRotatedStrings(input);
System.out.println(groups);
}
public static List<List<String>> groupRotatedStrings(List<String> strings)
{
return v1(strings);
// return v2(strings);
}
private static List<List<String>> v1(List<String> strings)
{
for (int i = 0; i < strings.size(); i++)
{
String s1 = strings.get(i);
for (int j = i+1; j < strings.size(); j++)
{
String s2 = strings.get(j);
System.out.println(s1 + " " + s2 + " " + isRotatedVersion(s1, s2));
}
}
return new ArrayList<>();
}
private static List<List<String>> v2(List<String> strings)
{
Map<String, List<String>> group = new HashMap<>();
for(String s : strings)
group.compute(genHash(s), (k, v) -> v == null ? new ArrayList<>() : v).add(s);
return new ArrayList<>(group.values());
}
/*
* Wrong method of hashing the string.
*/
private static String genHash(String s)
{
if(s.length() == 0 || s == null)
return null;
/*
* abc => a-b + b-c + c-a + (a + b + c)
* bca => b-c + c-a + a-b + (b + c + a)
* cba => c-b + b-a + a-c + (c + b + a) => should not be the same hashcode
*/
char prev = s.charAt(0);
char curr = 0;
int sum = prev;
int sumDiff = 0;
for(int i = 1; i < s.length(); i++)
{
curr = s.charAt(i);
sumDiff += (prev - curr);
sum += curr;
prev = curr;
}
if(s.length() > 1)
{
sumDiff += (curr - s.charAt(0));
}
return String.valueOf(sum + sumDiff);
}
private static boolean isRotatedVersion(String s1, String s2)
{
if(s1 == null)
return s1 == s2;
if(s1.length() != s2.length())
return false;
return (s1 + s1).contains(s2);
}
}
Start with a brute force approach and then try to optimize the algorithm with a better run time complexity.