问题链接:https://leetcode.com/problems/partition-array-into-disjoint-intervals/
这个问题也是做Virtual Contest时做到的,要在数组A中找一个位置i,使得左子数组max(A[:i])<=min(A[i+1:])(这里的i和i+1都取到),maxLeft[i]表示A[:i]中最大元素,minRight[i:]表示A[i:]中最小元素,这样的话我们需要寻找第一个出现的索引i使得max(A[:i])<=min(A[i+1:]),DP表达式:maxLeft[i+1]=max(maxLeft[i],A[i]),minRight[i-1]=Math.min(minRight[i],A[i-1]);
因此这个问题可以用two-pass traverse来解决,代码如下:
class Solution {
public int partitionDisjoint(int[] A) {
int n=A.length;
int[] maxLeft=new int[n];
int[] minRight=new int[n];
maxLeft[0]=A[0];
for(int i=1;i<n;i++)
maxLeft[i]=Math.max(maxLeft[i-1],A[i]);
minRight[n-1]=A[n-1];
for(int i=n-2;i>=0;i--)
minRight[i]=Math.min(minRight[i+1],A[i]);
int i=0;
for(;i<n-1;i++)
if(maxLeft[i]<=minRight[i+1])
break;
return i+1;
}
}
时间和空间复杂度都是O(n)。
后来看到了一个大神的解法one pass,类似于max sum of subarray,真牛逼,代码如下:关键是这三个变量的含义,max存储的是当前遍历的最大元素,num表示max(A[:i-1]),当A[i]比num小时,说明左数组可以延伸到A[i]。当遍历到右数组时因为都是比num大的A[i]就不能延伸进左数组里面。
class Solution {
public int partitionDisjoint(int[] A) {
int num=A[0];
int size=0;
int max=num;
for(int i=1;i<A.length;i++)
{
max=Math.max(max,A[i]);
if(A[i]<num)
{
num=max;
size=i;
}
}
return size+1;
}
}