題目:給定陣列arr,設長度為n,輸出arr的最長遞增子串行。(如果有多個答案,請輸出其中字典序最小的)這題好不容易寫出了動歸,結果超時了。。。。難過eg: 輸入:[2,1,5,3,6,4,8,9,7]
輸出:[1,3,4,8,9]
說一下另一種解法,還是看別人的**理解了很久。貪心+二分。
首先在動歸中有乙個操作,是查詢當前元素位置之前,第乙個小於當前元素的值,正是這個查詢操作導致動歸解法的時間複雜度變成了
然後說一下具體的解法,首先使用乙個陣列 lens 來儲存當前元素所能構成的最長上公升子串行,然後使用乙個陣列 flags 來儲存上公升子串行的臨時元素,但是要注意這個陣列中的元素並不一定是最終結果,其作用主要是輔助更新 lens 陣列,最終的最長上公升子串行的構成也是由 lens 和原始陣列 arr 生成的。
首先原始陣列為 arr = ,我們定義乙個最大長度max來記錄所能達到的最大上公升子串行的長度,初始化 flags = ,lens = ,使用迴圈從第1個元素開始遍歷每個元素(陣列元素從第0個開始計算),每當到達乙個元素i,判斷當前元素 arr[i] 和 flags[max-1] 的大小(這裡的 flags[max-1] 是flags的最後乙個元素有效元素),
1. 如果二者相等的話,直接將 lens[i] 置為max,因為此時所能構成的最大長度是不變的,大小相等也不需要對元素進行替換;
2. 如果當前元素 arr[i] 大於 flags[max-1],那麼所能構成的最大長度 max++,flags[max-1]置為當前元素,並且更新 lens[i] 為 max;
3. 如果當前元素 arr[i] 是小於 flags[max-1]的,那麼說明最大長度不變,但是所構成的子串行中,arr[i] 作為候選元素,可能可以去替換序列中的某個元素,因此需要在 flags 中使用二分進行查詢,找到第乙個小於 arr[i] 的元素下標 index 進行替換,替換之後,更新 lens[i] 為 index+1(按照之前提到的 flags 中的元素位置是和最長上公升子串行繫結的,flags中的位置實際就是最長上公升子串行的位置,因此 index 表示了從0到index的子串行的長度-1,所以 index+1 表示的是到元素 flags[i] 所能構成的子串行的長度),這一塊當時理解費了點力氣。。
經過上述步驟,可以計算出 lens = ,然後再次使用貪心演算法獲得最終結果。
由於題目要求的是最小字典,我們在計算 flags 和 lens 的時候已經按照這個邏輯進行了,並且我們得到了最大長度是5,我們在 lens 中可以看到,存在多個元素所能構成的最大長度相等的情況,那麼應該怎麼去判斷哪個是小字典的呢。
首先明確 lens 值相等有兩種情況,1. 元素值相等,那麼能夠構成的最長序列的長度自然相等,這種情況對於字典大小是沒有影響的;2.後面元素的值小於前面元素的值,更新 lens 後二者的值相等。
從上面的分析就可以得到,第一種情況可以忽略不計,那相等的**就是第二種情況,以及在對第二種情況的分析中我們也知道了,對於 lens 相等的元素,越靠後的值是越小的,那麼我們就可以從後向前遍歷,從 lens 值等於max 的位置開始,判斷當前值是不是等於 max,是的話直接拿到當前元素,max--,這樣也就直接跳過了前面的等於max的值,進入了下乙個位置的挑選。
即選出的 lens 中的元素對應的位置為 1,3,5,6,7,對應 arr 中的元素為 1,3,4,8,9.
完整**如下:
public static int lis (int arr) else
} int res = new int[max];
for(int i = arr.length-1;i>=0;i--)
} return res;
} public static int findfirst(int arr,int i, int index) else
} return left;
}
刷題之路 最長上公升子串行
這是乙個經典的lis 即最長上公升子串行 問題,請設計乙個盡量優的解法求出序列的最長上公升子串行的長度。給定乙個序列a及它的長度n 長度小於等於500 請返回lis的長度。例如1,2,3,2,4,5,3,6,7,5,8,lis就為12345678,長度為8 經典動態規劃問題,確定初始狀態,當以第乙個...
刷題 最長上公升子串行 最大上公升子串行和
關於子串行的問題做個記錄 一 最長上公升子串行 題目描述剝離,不管時搬箱子還是其他,一般來說,只要符合求後面的值比前面的大的序列長度基本上能套用 lis解法 1 動態規劃 找到序列1 7 3 5 9 4 8最長上公升子串行 找到初始化條件 狀態轉移方程 初始化 對於序列中的每個元素來說,它本身的長度...
LintCode刷題 最長上公升連續子串行
問題描述 給定乙個整數陣列 下標從 0 到 n 1,n 表示整個陣列的規模 請找出該陣列中的最長上公升連續子串行。最長上公升連續子串行可以定義為從右到左或從左到右的序列。樣例 給定 5,4,2,1,3 其最長上公升連續子串行 lics 為 5,4,2,1 返回4.給定 5,1,2,3,4 其最長上公...