Given an integer array nums, partition it into two (contiguous) subarrays left and right so that:
- Every element in
leftis less than or equal to every element inright. leftandrightare non-empty.lefthas 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 <= 1e5
- 0 <= nums[i] <= 1e6
- There is at least one valid answer for the given input.
Solution
第一次尝试从两边贪心找,但是数组并不有序,在如下样例 WA:
[32,57,24,19,0,24,49,67,87,87]
int partitionDisjoint(int* nums, int numsSize){
int left, right, lmax, rmin;
left = 0;
right = numsSize - 1;
lmax = nums[left];
rmin = nums[right];
while (left < right) {
if (nums[left] > lmax) lmax = nums[left];
if (nums[right] < rmin) rmin = nums[right];
if (rmin >= lmax) {
right--;
} else {
left++;
}
}
return left + 1;
}
题解方法:从左往右遍历数组,如果当前元素 nums[i] 不大于左边所有元素的最大值 leftmax 就更新 pos。注意等于的时候先不更新,后面再遇到一个严格小于的才更新,保证左边集合最小。遍历完左集合后右边所有的元素都会大于等于左集合最大元素,pos 也就一直不会更新,直到遍历结束就可以得到正确的 pos。
int partitionDisjoint(int* nums, int numsSize){
int i, pos, leftmax, curmax;
pos = 0;
leftmax = curmax = nums[0];
for (i = 0; i < numsSize; i++) {
if (nums[i] > curmax) curmax = nums[i];
if (nums[i] < leftmax) {
leftmax = curmax;
pos = i;
}
}
return pos + 1;
}