You are given an array nums
. You can rotate it by a non-negative integer k
so that the array becomes [nums[k], nums[k + 1], ... nums[nums.length - 1], nums[0], nums[1], ..., nums[k-1]]
. Afterward, any entries that are less than or equal to their index are worth one point.
nums = [2,4,1,3,0]
, and we rotate by k = 2
, it becomes [1,3,0,2,4]
. This is worth 3
points because 1 > 0
[no points], 3 > 1
[no points], 0 <= 2
[one point], 2 <= 3
[one point], 4 <= 4
[one point].Return the rotation index k
that corresponds to the highest score we can achieve if we rotated nums
by it. If there are multiple answers, return the smallest such index k
.
Example 1:
Input: nums = [2,3,1,4,0] Output: 3 Explanation: Scores for each k are listed below: k = 0, nums = [2,3,1,4,0], score 2 k = 1, nums = [3,1,4,0,2], score 3 k = 2, nums = [1,4,0,2,3], score 3 k = 3, nums = [4,0,2,3,1], score 4 k = 4, nums = [0,2,3,1,4], score 3 So we should choose k = 3, which has the highest score.
Example 2:
Input: nums = [1,3,0,2,4] Output: 0 Explanation: nums will always have 3 points no matter how it shifts. So we will choose the smallest k, which is 0.
Constraints:
1 <= nums.length <= 105
0 <= nums[i] < nums.length
This problem asks to find the rotation index k
that maximizes the score after rotating the array nums
. The score is calculated by counting the number of elements nums[i]
such that nums[i] <= i
after rotation. A brute-force approach would try all possible rotations, which has a time complexity of O(n²), where n is the length of nums
. However, a more efficient solution exists using the concept of prefix sums and difference arrays.
Approach:
Instead of directly calculating the score for each rotation, we use a clever observation: the change in score when rotating from k
to k+1
can be efficiently calculated.
Difference Array: Create a difference array d
of size n
. This array will store the change in score when moving from one rotation to the next. Initially, d
is filled with zeros.
Calculate Difference: For each element nums[i]
in the original array:
l
and r
where nums[i]
contributes to the score.l = (i + 1) % n
: The index where nums[i]
starts contributing to the score after the rotation.r = (n + i + 1 - nums[i]) % n
: The index where nums[i]
stops contributing to the score after the rotation.d[l]
(to account for the added contribution) and decrement d[r]
(to account for the removed contribution). This is because nums[i]
contributes to the score from index l
to r-1
(inclusive).Prefix Sum: Calculate the prefix sum of d
. The prefix sum s[k]
represents the total score after rotating by k
.
Find Maximum: Iterate through the prefix sum array s
to find the maximum score mx
and the corresponding index ans
(smallest index with the maximum score).
Time Complexity Analysis:
d
: O(n)d
: O(n)Therefore, the overall time complexity of this solution is O(n).
Space Complexity Analysis:
The space complexity is dominated by the difference array d
, which has a size of n
. Thus, the space complexity is O(n).
class Solution:
def bestRotation(self, nums: List[int]) -> int:
n = len(nums)
d = [0] * n # Difference array
for i, v in enumerate(nums):
l, r = (i + 1) % n, (n + i + 1 - v) % n
d[l] += 1 # Increment at l
d[r] -= 1 # Decrement at r
s = 0 # Prefix sum
mx = -1 # Maximum score
ans = n # Index of maximum score (initialized to n)
for k, t in enumerate(d):
s += t # Calculate prefix sum
if s > mx:
mx = s
ans = k # Update index if a better score is found
return ans
The code directly implements the steps described in the approach section. The use of the modulo operator %
handles the circular nature of array rotation effectively. The prefix sum efficiently accumulates the score changes, leading to the O(n) time complexity. The other languages (Java, C++, Go) follow a very similar structure and logic.