1. 程式人生 > >Leetcode 915. 分割陣列

Leetcode 915. 分割陣列

即使自己做了幾遍,還是沒有真正的開竅,領會精髓。第一眼看上去,這是一道陣列分割的題目。

 

給定一個數組 A,將其劃分為兩個不相交(沒有公共元素)的連續子陣列 left 和 right, 使得:

  • left 中的每個元素都小於或等於 right 中的每個元素。
  • left 和 right 都是非空的。
  • left 要儘可能小

思路一:那麼是按索引位置先分割,然後用暴力法比較?很容易得到O(n^3)解決方案(AC)
leetcode對時間複雜度的要求就是如此苛刻。
顯然這個是糟糕的實踐。

class Solution {
    public int partitionDisjoint(int[] A) {
        for(int i=1; i < A.length; i++){
            int flag = 0;
            for(int j=0; j < i; j++){
                for(int k=i;k<A.length;k++){
                    if (A[j] > A[k]) flag=1; break;
                }
                if(flag == 1) break;
            }
            if (flag==0) return i;
        }
        return 0;
    }
}

 

思路二:提煉維度。這裡說的維度,是在陣列迭代過程中產生的,也是貪心演算法的概念。比如你在沙灘上散步,背後留下的是你之前走過的腳印,每個腳印都是獨一無二的,輪廓是一樣的,但是腳印的力度、深淺、相對位置等因素不盡相同。 當然,如果有必要你可以拿一把尺子、一支筆、一張紙,當你每踩下一步,都能以資料的形式把每一步給量化。

維度只有在集合中才能體現出來。單一的個體不存在大和小,高和低這種概念。在陣列中,通過線性迭代會產生集合的維度,這種維度在迭代的過程中也是一直變化的。

回到Leetcode題目本身,left 中的每個元素都小於或等於 right

 中的每個元素。顯然,left和right各是一個集合,而這裡需要考慮left中最大值(leftMax)和right中最小值(rightMin)這2個維度,只有當滿足leftMax <= rightMin的時候就能得到答案。

class Solution {
    public int partitionDisjoint(int[] A) {
        int leftMax = A[0], rightMin = A[0], index=0;
        for(int i=0;i<A.length;i++){
            if(A[i] < rightMin){
                rightMin=leftMax;
                index=i;
            }
            leftMax=Math.max(leftMax, A[i]);
        }
        return index+1;
    }
}