The core idea behind "shifting" is that every letter in the string moves forward by the same amount. "abc" shifted by 1 becomes "bcd", shifted by 2 becomes "cde", and so on. The shift wraps around, so "xyz" shifted by 1 becomes "yza", and eventually you get back to "abc" after 26 shifts.
Two strings belong to the same shifting sequence if they have the same length and the same pattern of differences between consecutive characters. For example, "abc" has differences [1, 1] (b-a=1, c-b=1), and "xyz" also has differences [1, 1] (y-x=1, z-y=1). So they're in the same group.
The wrap-around needs care. "az" has a difference of 25 (z-a=25), and "ba" also has a difference of 25 (a-b = -1, but mod 26 = 25). So "az" and "ba" are in the same group.
This gives a way to group: compute the differences between consecutive characters (mod 26) for each string, and strings with identical difference sequences belong to the same group.
1 <= strings.length <= 200 → The input is small enough that even an O(n^2) pairwise comparison runs comfortably, so correctness, not raw speed, drives the choice of approach.1 <= strings[i].length <= 50 → Strings are short, so computing a difference key per string is cheap.strings[i] consists of lowercase English letters → Only 26 characters, so differences fall in the range [0, 25] and a single mod 26 handles every wrap-around.For every pair of strings, check whether they belong to the same shifting sequence. Two strings are in the same group if they have the same length and one can be shifted to match the other. To check this, compute the shift amount from the first character and verify the same shift holds at every position.
Pick a string, compare it against every other ungrouped string, and collect the matches into one group.
Loading animation...
The pairwise comparison repeats work: each string is compared against many others, and the comparison itself recomputes shifts from scratch. The next approach replaces the comparison with a single key computed per string, so strings that share a key fall into the same group without ever being compared directly.
Instead of comparing every pair, assign each string a signature that identifies which shift group it belongs to. Two strings with the same signature go into the same group.
The shift pattern of a string is fixed by the differences between consecutive characters. "abc" has differences [1, 1], "bcd" also has differences [1, 1], and "xyz" also has differences [1, 1]. But "acef" has differences [2, 2, 1], a different pattern.
For each string, compute its difference sequence (mod 26 to handle wrap-around), use that sequence as a hash map key, and group strings by key. A single-character string has no consecutive pairs, so its difference sequence is empty, and all single-character strings share that empty key.
Shifting a string by k adds k (mod 26) to every character, which leaves every consecutive difference unchanged: (s[i+1]+k) - (s[i]+k) = s[i+1] - s[i]. So all strings in one shift sequence have the same difference sequence, and the difference sequence is a canonical representation of the group. The converse holds too: equal length plus equal differences forces a single constant offset between the two strings, which is exactly a shift.
The mod 26 handles wrap-around. When 'a' follows 'z' (as in "za"), the raw difference is -25, but (-25 + 26) % 26 = 1, which records that the next character is 1 step forward in the circular alphabet.
(s[i+1] - s[i] + 26) % 26.Loading animation...
This is optimal: O(n * k) time is the lower bound, since every character of every string has to be read at least once to determine its group.