Given an integer array nums
, partition it into two (contiguous) subarrays left
and right
so that:
left
is less than or equal to every element in right
.left
and right
are non-empty.left
has the smallest possible size.Return the length of left
after such a partitioning.
Test cases are generated such that partitioning exists.
Example 1:
Input: nums = [5,0,3,8,6]
Output: 3
Explanation: left = [5,0,3], right = [8,6]
Example 2:
Input: nums = [1,1,1,0,6,12]
Output: 4
Explanation: left = [1,1,1,0], right = [6,12]
Constraints:
2 <= nums.length <= 10^5
0 <= nums[i] <= 10^6
A brute-force approach would be to iterate through all possible split points of the array, creating left
and right
subarrays at each split. For each split, check if the maximum element in left
is less than or equal to the minimum element in right
. The first split that satisfies this condition gives the desired length of the left
subarray.
def partition_array_naive(nums):
for i in range(1, len(nums)):
left = nums[:i]
right = nums[i:]
if max(left) <= min(right):
return i
return len(nums) # Should not happen as problem guarantees a solution
O(n^2) in the worst case because, for each possible split point, we compute max(left)
and min(right)
which take O(n) time.
O(1) since we are only using a constant amount of extra space.
We can improve the time complexity by pre-computing the maximum value from the left and the minimum value from the right for each index. This way, we only need to iterate once to find the partition point.
max_left
and min_right
, of the same size as the input array nums
.max_left[i]
stores the maximum value in nums[0...i]
. We can compute this in one pass.min_right[i]
stores the minimum value in nums[i...n-1]
. We can compute this in one pass from right to left.i = 1
to n-1
. If max_left[i-1] <= min_right[i]
, then i
is the partition index. Return i
.def partition_array_optimal(nums):
n = len(nums)
max_left = [0] * n
min_right = [0] * n
max_left[0] = nums[0]
for i in range(1, n):
max_left[i] = max(max_left[i - 1], nums[i])
min_right[n - 1] = nums[n - 1]
for i in range(n - 2, -1, -1):
min_right[i] = min(min_right[i + 1], nums[i])
for i in range(1, n):
if max_left[i - 1] <= min_right[i]:
return i
return n # Should not happen as problem guarantees a solution
O(n) because we iterate through the array three times.
O(n) due to the max_left
and min_right
arrays.
2 <= nums.length
. So, an empty array is not a valid input.nums
is sorted in ascending order, the first element forms the left
subarray.nums
is sorted in descending order, the algorithm will iterate until the end to find the split.