Given an array nums
, return true
if the array was originally sorted in non-decreasing order, then rotated some number of positions (including zero). Otherwise, return false
. There may be duplicates in the original array.
Note: An array A
rotated by x
positions results in an array B
of the same length such that B[i] == A[(i+x) % A.length]
for every valid index i
.
For example:
[3,4,5,1,2]
should return true
[2,1,3,4]
should return false
[1,2,3]
should return true
Here are some edge cases to consider:
When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
The brute force method to check if an arrangement of numbers is sorted and rotated involves trying out all possible rotation points. We examine each rotation to see if it results in a sorted sequence. If we find a sorted sequence after rotating, then the original arrangement satisfies the condition.
Here's how the algorithm would work step-by-step:
def check_if_array_is_sorted_and_rotated_brute_force(array):
array_length = len(array)
# Iterate through all possible rotations.
for rotation_index in range(array_length):
rotated_array = array[rotation_index:] + array[:rotation_index]
# Check if the rotated array is sorted.
is_sorted = True
for index in range(array_length - 1):
if rotated_array[index] > rotated_array[index + 1]:
is_sorted = False
break
# If a sorted rotation is found, return True.
if is_sorted:
return True
# If no sorted rotation is found, return False. This covers the non-rotated case as well
return False
To determine if an array is sorted and rotated, we aim to find the potential 'break' in the sorted order efficiently. We identify where the sorted order is disrupted, and then verify that sorting is consistent before and after that break. This avoids checking all possible rotation points.
Here's how the algorithm would work step-by-step:
def is_sorted_and_rotated(numbers) -> bool:
disruption_count = 0
array_length = len(numbers)
# Find disruptions in the sorted order
for i in range(array_length):
if numbers[i] > numbers[(i + 1) % array_length]:
disruption_count += 1
# Already sorted condition
if disruption_count == 0:
return True
# More than one disruption means not rotated
if disruption_count > 1:
return False
# Check rotation conditions
if numbers[array_length - 1] <= numbers[0]:
# This is the potential rotated point we expect
return True
return False
Case | How to Handle |
---|---|
Null or empty array | Return true since an empty array can be considered sorted and rotated. |
Array with one element | Return true since a single element array is trivially sorted and rotated. |
Array already sorted in strictly increasing order | The algorithm should correctly identify this as a valid rotated array (rotation count of 0). |
Array sorted in descending order | The algorithm should return false as rotating a descending array won't result in a sorted one. |
Array with all identical elements | Return true since even with identical elements, it can be considered sorted and rotated. |
Array with duplicate values that are not strictly increasing after rotation | The logic must handle duplicate values correctly, ensuring that only a single 'break' point exists where the previous element is greater than the current one, disregarding duplicates. |
Array with large integers that could cause integer overflow | The comparison should avoid potential integer overflow issues by using appropriate data types or checking for overflow during comparisons. |
Array with a very large number of elements | Ensure that the algorithm's time complexity is optimal, ideally O(n), to avoid timeouts with large arrays. |