2016-05-11 75 views
0

好吧,說我有一個類型爲int的強類型SortedSet。我想找到集合中小於x的最大數字。如何高效地搜索具有不等式的排序集?

也許這是錯誤的數據結構,但我直覺的想法是,我有一個排序的集合。毫無疑問,我應該能夠通過.NET框架進行這種搜索。

回答

2

由於SortedSet不提供通過索引直接訪問你必須依靠枚舉(線性搜索 - 爲O(n))。一種可能更好的方法是使用SortedSet.GetViewBetweenLast,但它看起來不像你可以得到的最後一個元素,但無論如何都沒有枚舉所有元素。

收集與指數直接訪問(即List)將讓你做O(LG n)的二進制搜索性能 - 因此使用List.BinarySearch時,如果你需要大量的複製搜索到列表可以與ToList提供更好的整體性能(這給你你正在尋找的下一個元素的位置)。

// starting sample for BinarySearch approach 
// not handling case where item not in the list (x = 1). 
// List have to be sorted which is the case starting from sorted set: sortedSet.ToList() 
var list = new List<int>{ 1,3, 5, 7, 8,9}; 
var index = list.BinarySearch(8); 
Console.WriteLine(index < 0 ? list[~index - 1] : list[index-1]); 
+1

值得一提的是,必須在執行BinarySearch之前對列表進行排序 - 從msdn頁面的備註部分:「列表必須已根據比較器實現進行排序;否則結果不正確。」 –

+0

@zohar OP從SortedSet開始,所以ToList將會產生排序列表。事實上,如果從其他一些數據開始,那麼排序是第一步 - 但這比原始的線性搜索更糟糕。 –

+0

我完全同意你的看法,這就是爲什麼我提高了你的答案,但這也是我認爲值得一提的原因 - 你的例子沒有在有序集合上使用'.ToList()'... –

2

除非我失去了一些東西,使用Linq的LastOrDefault擴展方法:

var lastBefore = set.LastOrDefault(num => num < x); // x is your search number 
if (lastBefore < set.ElementAt(0)) 
{ 
    // Nothing in the set is smaller 
} 
else 
{ 
    // lastBefore is the last number smaller then search number 
} 
+0

請注意,即使集合被排序並且通常會期望O(lg n)性能,但這是O(n),但就我所知,這是使用'SortedSet'的最佳結果。 –