【Leetcode】1673. Find the Most Competitive Subsequence

記錄演算法發表於2020-11-30

題目地址:

https://leetcode.com/problems/find-the-most-competitive-subsequence/

給定一個陣列 A A A,求其字典序最小的長 k k k的子序列。

思路是單調棧。求長 k k k的子序列相當於在 A A A裡刪掉 l A − k l_A-k lAk個數字。我們用一個變數 r r r標記還可以刪多少個數字,一開始賦值為 l A − k l_A-k lAk。接著開一個從棧底到棧頂嚴格單調上升的棧,如果棧非空並且棧頂大於新來的數,並且還能刪數字(指 r > 0 r>0 r>0成立),則出棧,並將 r r r 1 1 1,直到棧空或者棧頂小於等於新來的數或者 r = 0 r=0 r=0(這時沒法刪了),接著將新來的數入棧(如果棧滿,說明新來的數無法入棧,則多刪一個數,將 r r r減去 1 1 1)。最後棧底到棧頂的陣列即為所求。演算法正確性證明,只需要注意每次可以刪的時候(這裡的刪主要指的是pop棧頂),刪總是比不刪好。程式碼如下:

public class Solution {
    public int[] mostCompetitive(int[] nums, int k) {
        int[] res = new int[k];
        int idx = 0, rem = nums.length - k;
        for (int i = 0; i < nums.length; i++) {
        	// 如果棧非空並且棧頂大於新來的數,並且還能刪數字,則出棧
            while (idx > 0 && res[idx - 1] > nums[i] && rem > 0) {
                idx--;
                rem--;
            }
            
            if (idx < res.length ) {
                res[idx++] = nums[i];
            } else {
                rem--;
            }
        }
        
        return res;
    }
}

時間複雜度 O ( l A ) O(l_A) O(lA),空間 O ( 1 ) O(1) O(1)

相關文章