[英]Finding the minimum distance between any pair of equal elements in an array
給定一些整數數組A = [a 0 ,a 1 ,...,a n ],找到i和j之間的最小距離,使得i = a j和i!= j(或表示沒有這樣的指數存在)。
所以我在C ++中實現了一種天真的O(n 2 )方法,包括遍歷數組尋找相等的元素並適當地更新最小距離:
#include <vector>
#include <climits>
#include <algorithm>
int MinPair(const std::vector<int>& nums)
{
int ret = std::numeric_limits<int>::max();
for(int i = 0; i != nums.size(); ++i)
{
for(int j = 0; j != i; ++j)
{
if(nums[i] == nums[j])
ret = std::min(ret, i - j);
}
}
if(ret == std::numeric_limits<int>::max())
return -1;
return ret;
}
這很好用,但我被告知有一個更“有效”的實現存在涉及std :: map,沒有更多關於什么更有效的澄清。 也就是說,可以遍歷輸入數組並在地圖中存儲元素的第一次出現,並且對於每次后續出現,找到該出現與地圖中該元素的第一個索引之間的距離。 如果該距離小於當前最小值,則我們更新該最小值。
但是,我沒有看到這更“有效”的方式。 時間復雜度方面,你仍然需要遍歷輸入數組(O(n)),並使用std :: map :: find來識別元素是否是第一次出現也是O(n) ,總復雜度為O(n 2 )。 在空間復雜性方面,除了數組/向量之外,還必須存儲地圖。 我到底錯過了什么?
編輯:我錯誤地假設map :: find是O(n); 插入和查找操作實際上是O(log n),即使假設基本實現使用二進制搜索之類的東西,也可以立即看到。
我最初發布的編碼解決方案類似於grigor提到的解決方案。 然后我意識到有一個明顯的優化,使得整個事情在O(N)時間內工作,以獲得最佳案例和平均情況。
typedef pair<bool, int> LastPositionFound;
int MinPair(const std::vector<int>& nums)
{
unordered_map<int, LastPositionFound> table; // maps value found in array to the last position that value was seen at.
int best_distance = -1;
for (size_t index = 0; index < nums.size(); index++)
{
int value = nums[index];
LastPositionFound& lpf = table[value]; // returns {false,0} if not found
if (lpf.first)
{
int distance = index - lpf.second;
if ((distance < best_distance) || (best_distance == -1))
{
best_distance = distance;
}
}
// update reference to hash table entry
lpf.first = true;
lpf.second = index;
}
return best_distance;
}
您可以將每個元素映射到一組索引。 所以你有類似map<int, set<int>> m
,並通過你的向量: for(int i = 0, i < nums.size(); ++i) m[nums[i]].insert(i)
。 之后,您可以遍歷地圖,如果元素有多個索引,則查找索引之間的最小距離。 應該是O(nlog(n))。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.