簡體   English   中英

在圓形陣列中找到子序列的第k個最小數

[英]Find k-th smallest number of a subsequence in a circular array

嗨,我正在嘗試從IEEEXtreme 2014解決此問題:

您會得到N個以圓形排列的整數。 有N種方法可以選擇長度為M(M <N)的連續子序列。 對於任何這樣的子序列,我們都可以找到該子序列的“ K”值。 給定子序列的“ K”值是該子序列中第K個最小的數字。 給定N的數組,找到所有可能的子序列中最小的K值。 例如N = 5 M = 3 K = 2且數組1 5 3 4 2給出結果2。

我的方法是,首先創建一個排序數組列表,將新輸入插入正確的位置。 我將前M個整數添加到列表中。 記錄第K個最小值。 然后,我繼續刪除最舊的整數,並將下一個整數添加到列表中,並將新的第K個值與舊的進行比較。 這是我的排序數組列表。

class SortedArrayList extends ArrayList {  
    public void insertSorted(int value) {        
        for (int i = size()-1; i >= 0; i--){
            if( value - (Integer)get(i)>=0){            
                    add(i+1,new Integer(value));
                    return;
            }
        }
        add(0,new Integer(value));
    }
}

我認為這種蠻力方法效率不高,但尚無法提出任何想法。 您知道對此有更好的解決方案嗎? 謝謝。

這是一個更有效的解決方案:

  1. 讓我們擺脫循環性,使事情變得更簡單。 我們可以通過將給定數組附加到自身來做到這一點。

  2. 我們可以假設輸入中的所有數字都是唯一的。 如果不是這種情況,我們可以使用一對(element, position)代替每個元素。

  3. 讓我們對給定的數組進行排序。 現在,我們將對答案使用二進制搜索(即,排序后的全局數組中所有子數組中第k個最小元素的位置)。

  4. 如何檢查固定候選x至少等於第k-th最小數字? 讓我們用1標記小於或等於x的數字的所有位置,用0標記其余的位置。 現在我們只需要檢查是否存在長度為M的子數組,其中至少包含k個子數組。 我們可以使用滾動總和在線性時間內做到這一點。

時間復雜度為: O(N log N)用於對輸入進行排序+ O(N log N)用於在答案上進行二進制搜索(存在O(log N)檢查,並且每個檢查都在線性時間內完成,如4中所述)。 因此,總時間復雜度為O(N log N)

PS我可以想到其他幾種具有相同時間復雜度的解決方案,但是這似乎是最容易實現的解決方案(它不需要任何自定義數據結構)。

對於圓形陣列問題,更優雅的解決方案是簡單地使用模。 因此,如果您只是在尋找一種模擬圓形陣列的解決方案,我建議您這樣做:

int n = somevalue;//the startingpoint of the subsequence
int m = someothervalue;//the index in the subsequence

int absolute_index = (n + m) % N;

其中N是序列中元素的總數。

進一步提高效率的下一步將是存儲第k個值的索引。 這樣,您只需要每第M個步驟(最壞的情況)計算一個新的K值,然后將其與其他步驟中的一個新值進行比較即可。 但是我會留給你;)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM