Before attempting this problem, you should be comfortable with:
Array Traversal - Iterating through arrays and comparing adjacent elements
Modulo Arithmetic - Using modulo to handle circular array indexing (wrap-around)
Sorted Array Properties - Understanding non-decreasing order and rotation concepts
1. Brute Force
Intuition
A sorted and rotated array can be thought of as taking a sorted array and moving some elements from the end to the beginning. For example, [3,4,5,1,2] is [1,2,3,4,5] rotated. We can verify this by sorting the array and checking if our original array matches some rotation of the sorted version.
Algorithm
Create a sorted copy of the input array.
Try every possible rotation (0 to n-1 positions).
For each rotation amount i, compare the original array with the sorted array rotated by i positions.
To compare, check elements from position n-i to n-1 of the sorted array against the beginning of the original, then elements from position 0 to n-i-1 against the rest.
If any rotation matches the original array, return true.
publicclassSolution{publicbooleancheck(int[] nums){int n = nums.length;int[] sortedNums = nums.clone();Arrays.sort(sortedNums);for(int i =0; i < n; i++){boolean match =true;int idx =0;for(int j = n - i; j < n && match; j++){if(nums[idx]!= sortedNums[j]){
match =false;}
idx +=1;}for(int j =0; j < n - i && match; j++){if(nums[idx]!= sortedNums[j]){
match =false;}
idx +=1;}if(match)returntrue;}returnfalse;}}
classSolution{public:boolcheck(vector<int>& nums){int n = nums.size();
vector<int> sortedNums = nums;sort(sortedNums.begin(), sortedNums.end());for(int i =0; i < n; i++){bool match =true;int idx =0;for(int j = n - i; j < n && match; j++){if(nums[idx]!= sortedNums[j]){
match =false;}
idx++;}for(int j =0; j < n - i && match; j++){if(nums[idx]!= sortedNums[j]){
match =false;}
idx++;}if(match)returntrue;}returnfalse;}};
classSolution{/**
* @param {number[]} nums
* @return {boolean}
*/check(nums){const n = nums.length;const sortedNums =[...nums].sort((a, b)=> a - b);for(let i =0; i < n; i++){let match =true;let idx =0;for(let j = n - i; j < n && match; j++){if(nums[idx]!== sortedNums[j]){
match =false;}
idx++;}for(let j =0; j < n - i && match; j++){if(nums[idx]!== sortedNums[j]){
match =false;}
idx++;}if(match)returntrue;}returnfalse;}}
publicclassSolution{publicboolCheck(int[] nums){int n = nums.Length;int[] sortedNums =(int[])nums.Clone();
Array.Sort(sortedNums);for(int i =0; i < n; i++){bool match =true;int idx =0;for(int j = n - i; j < n && match; j++){if(nums[idx]!= sortedNums[j]){
match =false;}
idx++;}for(int j =0; j < n - i && match; j++){if(nums[idx]!= sortedNums[j]){
match =false;}
idx++;}if(match)returntrue;}returnfalse;}}
funccheck(nums []int)bool{
n :=len(nums)
sortedNums :=make([]int, n)copy(sortedNums, nums)
sort.Ints(sortedNums)for i :=0; i < n; i++{
match :=true
idx :=0for j := n - i; j < n && match; j++{if nums[idx]!= sortedNums[j]{
match =false}
idx++}for j :=0; j < n-i && match; j++{if nums[idx]!= sortedNums[j]{
match =false}
idx++}if match {returntrue}}returnfalse}
class Solution {funcheck(nums: IntArray): Boolean {val n = nums.size
val sortedNums = nums.clone()
sortedNums.sort()for(i in0 until n){var match =truevar idx =0var j = n - i
while(j < n && match){if(nums[idx]!= sortedNums[j]){
match =false}
idx++
j++}
j =0while(j < n - i && match){if(nums[idx]!= sortedNums[j]){
match =false}
idx++
j++}if(match)returntrue}returnfalse}}
classSolution{funccheck(_ nums:[Int])->Bool{let n = nums.count
let sortedNums = nums.sorted()for i in0..<n {var match =truevar idx =0var j = n - i
while j < n && match {if nums[idx]!= sortedNums[j]{
match =false}
idx +=1
j +=1}
j =0while j < n - i && match {if nums[idx]!= sortedNums[j]{
match =false}
idx +=1
j +=1}if match {returntrue}}returnfalse}}
Time & Space Complexity
Time complexity: O(n2)
Space complexity: O(n)
2. Sliding Window
Intuition
If we imagine the array as circular (the last element connects back to the first), a valid sorted-and-rotated array should have a contiguous segment of length n where elements are in non-decreasing order. We can simulate this circular behavior by conceptually doubling the array and looking for n consecutive non-decreasing elements.
Algorithm
Iterate through indices 1 to 2n-1, treating the array as circular using modulo operations.
Maintain a count of consecutive non-decreasing pairs.
If the current element (at index i % n) is greater than or equal to the previous element, increment the count.
Otherwise, reset the count to 1.
If at any point the count reaches n, we found a valid sorted sequence, so return true.
Handle the edge case where n equals 1 by returning true at the end.
publicclassSolution{publicboolCheck(int[] nums){int N = nums.Length;int count =1;for(int i =1; i <2* N; i++){if(nums[(i -1)% N]<= nums[i % N]){
count++;}else{
count =1;}if(count == N){returntrue;}}return N ==1;}}
funccheck(nums []int)bool{
N :=len(nums)
count :=1for i :=1; i <2*N; i++{if nums[(i-1)%N]<= nums[i%N]{
count++}else{
count =1}if count == N {returntrue}}return N ==1}
class Solution {funcheck(nums: IntArray): Boolean {val N = nums.size
var count =1for(i in1 until 2* N){if(nums[(i -1)% N]<= nums[i % N]){
count++}else{
count =1}if(count == N){returntrue}}return N ==1}}
classSolution{funccheck(_ nums:[Int])->Bool{letN= nums.count
var count =1for i in1..<(2*N){if nums[(i -1)%N]<= nums[i %N]{
count +=1}else{
count =1}if count ==N{returntrue}}returnN==1}}
Time & Space Complexity
Time complexity: O(n)
Space complexity: O(1)
3. Iteration
Intuition
In a sorted-and-rotated array, there can be at most one "break point" where a larger element is followed by a smaller element. This break point is where the rotation occurred. If we find more than one such break, the array cannot be a valid rotation of a sorted array.
Algorithm
Initialize a counter for the number of break points (where an element is greater than its next element).
Iterate through the array, comparing each element with the next one (using modulo to wrap around from the last element to the first).
If the current element is greater than the next element, increment the break counter.
If the counter exceeds 1 at any point, return false immediately.
After checking all pairs, return true (at most one break was found).
classSolution:defcheck(self, nums: List[int])->bool:
count, N =0,len(nums)for i inrange(N):if nums[i]> nums[(i +1)% N]:
count +=1if count >1:returnFalsereturnTrue
publicclassSolution{publicbooleancheck(int[] nums){int count =0,N= nums.length;for(int i =0; i <N; i++){if(nums[i]> nums[(i +1)%N]&&++count >1){returnfalse;}}returntrue;}}
classSolution{public:boolcheck(vector<int>& nums){int count =0, N = nums.size();for(int i =0; i < N; i++){if(nums[i]> nums[(i +1)% N]&&++count >1){returnfalse;}}returntrue;}};
classSolution{/**
* @param {number[]} nums
* @return {boolean}
*/check(nums){let count =0,N= nums.length;for(let i =0; i <N; i++){if(nums[i]> nums[(i +1)%N]&&++count >1){returnfalse;}}returntrue;}}
publicclassSolution{publicboolCheck(int[] nums){int count =0, N = nums.Length;for(int i =0; i < N; i++){if(nums[i]> nums[(i +1)% N]&&++count >1){returnfalse;}}returntrue;}}
funccheck(nums []int)bool{
count, N :=0,len(nums)for i :=0; i < N; i++{if nums[i]> nums[(i+1)%N]{
count++if count >1{returnfalse}}}returntrue}
class Solution {funcheck(nums: IntArray): Boolean {var count =0val N = nums.size
for(i in0 until N){if(nums[i]> nums[(i +1)% N]){
count++if(count >1){returnfalse}}}returntrue}}
classSolution{funccheck(_ nums:[Int])->Bool{var count =0letN= nums.count
for i in0..<N{if nums[i]> nums[(i +1)%N]{
count +=1if count >1{returnfalse}}}returntrue}}
Time & Space Complexity
Time complexity: O(n)
Space complexity: O(1)
Common Pitfalls
Forgetting to Check the Wrap-Around
A sorted and rotated array is circular, so you must compare the last element with the first element. Using nums[i] > nums[i + 1] without modulo wrapping misses the case where the "break" occurs between the last and first elements.
The problem allows non-decreasing order (duplicates are permitted). Checking for strict inequality nums[i] >= nums[i+1] instead of nums[i] > nums[i+1] incorrectly flags valid arrays like [1, 1, 1] or [2, 2, 3, 1, 1] as invalid.