Last Updated: March 31, 2026
We need to determine if one string is a rotation of another. A rotation means taking some number of characters from the front of the string and moving them to the back. For example, "cdeab" is a rotation of "abcde" because we moved the first two characters ("ab") to the end.
The first thing to notice: if s and goal have different lengths, the answer is immediately false. You can't rotate a string into a string of a different length. So that's our quick early exit.
The real question is: given two strings of the same length, how do we efficiently check if one is a rotation of the other?
1 <= s.length, goal.length <= 100 — With n up to 100, even O(n^3) would be fine. This problem is not about optimizing runtime. It's about recognizing a clean, elegant approach.s and goal consist of lowercase English letters. — No special characters or unicode to worry about. Simple character comparison works.The most direct approach: try every possible rotation of s and check if any of them equals goal. Since a string of length n has exactly n distinct rotations (including the original), we generate each one and compare.
To generate the k-th rotation, we take the substring from index k to the end and append the substring from index 0 to k. For "abcde" with k=2, that gives us "cde" + "ab" = "cdeab".
s and goal have different lengths, return false.k from 0 to n - 1:s[k..n-1] + s[0..k-1].goal, return true.false.This works but rebuilds the entire string for every rotation. Is there a way to check all rotations at once without constructing each one?
If you concatenate s with itself, every possible rotation of s appears as a contiguous substring inside s + s. For s = "abcde", s + s = "abcdeabcde" contains all five rotations as length-5 windows. So the question becomes: is goal a substring of s + s?
Any rotation of s by k positions gives s[k..n-1] + s[0..k-1]. The substring from index k to index k + n - 1 in s + s is exactly this rotation. So every rotation of s is a substring of s + s starting at some index between 0 and n-1.
The length check is critical. Without it, "a" would match inside "aa" even though "a" isn't a rotation of "aa".
s and goal have different lengths, return false.s with itself to get doubled.goal is a substring of doubled.true. Otherwise, return false.The concatenation trick is elegant, but it creates a new string of length 2n. Can we check the rotation property without allocating any extra strings?
For each possible starting position k in s, we check if the characters of s starting at k (wrapping around using modular arithmetic) match goal character by character. Instead of building s.substring(k) + s.substring(0, k), we use s.charAt((k + j) % n) to access the j-th character of the k-th rotation directly.
s and goal have different lengths, return false.k from 0 to n - 1:s[(k + j) % n] == goal[j] for all j from 0 to n - 1.true.false.