数组分段排序后连接、总体也有序,最多可分多少段
数组数任意可重复
int maxChunksToSorted(vector<int>& arr) {
// maxL[i]表示arr[0..i)的最大值,minR[i]表示arr[i..]的最小值
// maxL[i]<=minR[i]时可分
const int N = arr.size();
vector<int> maxL(N + 1, INT_MIN), minR(N + 1, INT_MAX);
for (int i = 0; i < N; i++) {
maxL[i+1] = max(maxL[i], arr[i]);
}
int ans = 0;
for (int i = N - 1; i >= 0; i--) {
minR[i] = min(minR[i+1], arr[i]);
if (maxL[i] <= minR[i]) ans++;
}
return ans;
}
上题解法可用。因为数组是[1,n]的排列,还可以简化
int maxChunksToSorted(vector<int>& arr) {
// 数组是[1,n]的排列,若maxL[i]==i,则在i后可断开左右
int ans = 0;
int maxL = INT_MIN;
for (int i = 0; i < arr.size(); i++) {
maxL = max(maxL, arr[i]);
if (maxL == i) ans++;
}
return ans;
}
最短无序子段,该子段排序后、整个数组也有序
int findUnsortedSubarray(vector<int>& nums) {
// 若数组有序,对任意nums[i]有:maxL[i]==nums[i]==minR[i]
// 从左往右检查,最右的违反maxL[i]==nums[i]的i是右边界
// 从右往左检查,最左的违反nums[i]==minR[i]的i是左边界
const int N = nums.size();
int maxL = INT_MIN, minR = INT_MAX;
int lo = 0, hi = -1; // 无序子段的左右边界
for (int i = 0, j = N - 1; i < N; i++, j--) {
maxL = max(maxL, nums[i]);
if (nums[i] != maxL) hi = i;
minR = min(minR, nums[j]);
if (nums[j] != minR) lo = j;
}
return hi - lo + 1;
}