Partition Array into Disjoint Intervals LT915

Given an array A, partition it into two (contiguous) subarrays left and right so that:

  • Every element in 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.  It is guaranteed that such a partitioning exists.

Example 1:

Input: [5,0,3,8,6]
Output: 3
Explanation: left = [5,0,3], right = [8,6]

Example 2:

Input: [1,1,1,0,6,12]
Output: 4
Explanation: left = [1,1,1,0], right = [6,12]

 

Note:

  1. 2 <= A.length <= 30000
  2. 0 <= A[i] <= 10^6
  3. It is guaranteed there is at least one way to partition A as described.

 Idea 1. max(nums[0]... nums[i]) <= min(nums[i+1],..nums[n-1]), build maxArray from left, minArray from right

Time comlexity: T(n)

Space complexity: T(n)

using index:

 1 class Solution {
 2     public int partitionDisjoint(int[] A) {
 3        int[] maxIndex = new int[A.length];
 4         for(int i = 1; i < A.length; ++i) {
 5             if(A[i] > A[maxIndex[i-1]]) {
 6                 maxIndex[i] = i;
 7             }
 8             else {
 9                 maxIndex[i] = maxIndex[i-1];
10             }
11         }
12         
13         int[] minIndex = new int[A.length];
14         minIndex[A.length-1] = A.length-1;
15         for(int i = A.length-2; i >= 0; --i) {
16             if(A[i] < A[minIndex[i+1]]) {
17                 minIndex[i] = i;
18             }
19             else {
20                 minIndex[i] = minIndex[i+1];
21             }
22         }
23         
24         for(int i = 0; i < A.length-1; ++i) {
25             if(A[maxIndex[i]] <= A[minIndex[i+1]]) {
26                 return i + 1;
27             }
28         }
29         
30         return 0;
31     }
32 }

No need to use index

class Solution {
     public int partitionDisjoint(int[] A) {
        int[] maxFromLeft = new int[A.length];
         maxFromLeft[0] = A[0];
         for(int i = 1; i < A.length; ++i) {
             maxFromLeft[i] = Math.max(maxFromLeft[i-1], A[i]);
         }
         
         int[] minFromRight = new int[A.length];
         minFromRight[A.length-1] = A[A.length-1];
         for(int i = A.length-2; i >= 0; --i) {
             minFromRight[i] = Math.min(minFromRight[i+1], A[i]);
         }
         
         for(int i = 0; i < A.length-1; ++i) {
             if(maxFromLeft[i] <= minFromRight[i+1]) {
                 return i + 1;
             }
         }
         
         return 0;
     }
 }

Idea 2. 从讨论里看到的妙解,只需要保持2个变量,localMax记录有效partition里的最大值, maxSoFar记录遍历至今的最大值,nums[0]...nums[paritionIndex] (localMax) | [nums[partitonIndex]...nums[i-1]| (maxSoFar),  遍历到一个数nums[i], 

paritionIndex 不变 if nums[i] >= localMax

paritionIndex = i, 需要包括nums[i], localMax也需要更新至maxSoFar

Time complexity: O(n)

Space complexity: O(1)

 1 class Solution {
 2     public int partitionDisjoint(int[] A) {
 3        int localMax = A[0];
 4        int maxSoFar = A[0];
 5        int partitionIndex = 0;
 6        for(int i = 1; i < A.length; ++i) {
 7            if(A[i] < localMax) {
 8                partitionIndex = i;
 9                localMax = maxSoFar;
10            }
11            maxSoFar = Math.max(maxSoFar, A[i]);
12        }
13         
14         return partitionIndex + 1;
15     }
16 }

posted on 2019-04-03 19:36  一直走在路上  阅读(96)  评论(0)    收藏  举报

导航