【python】求数组中两个元素的最小距离?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了【python】求数组中两个元素的最小距离?相关的知识,希望对你有一定的参考价值。

参考技术A 题目:给定一个数组,数组中含有重复元素,给定两个数组num1和num2,求这两个数字在数组中出现的最小距离。

分析:动态规划法。动态规划的方法可以把每次遍历的结果都记录下来从而减少遍历次数。当遍历数组时,会遇到以下两种情况:

(1)当遇到num1时,记录下num1值对应的数组下标的位置lastPos1,通过求lastPos1与上次遍历到num2下标位置的值lastPos2的差可以求出最近一次遍历到num1与num2的距离。

(2)当遇到num2时,记录下num2值对应的数组下标的位置lastPos2,通过求lastPos1与上次遍历到num2下标位置的值lastPos2的差可以求出最近一次遍历到num1与num2的距离。

code:

def minDis(arr, num1, num2):

    if arr is None or len(arr) <= 0:

        return 2 ** 32

    lastPos1 = -1

    lastPos2 = -1

    minDis = 2 ** 32

    i = 0

    while i < len(arr):

        if arr[i] == num1:

            lastPos1 = i

            if lastPos2 >= 0:

                minDis = min(minDis, abs(lastPos2 - lastPos1))

        if arr[i] == num2:

            lastPos2 = i

            if lastPos1 >= 0:

                minDis = min(minDis, abs(lastPos2 - lastPos1))

        i += 1

    return minDis

if __name__ == "__main__":

    arr = [4, 5, 6, 4, 7, 4, 6, 4, 7, 8, 5, 6, 4, 3, 10, 8]

    num1 = 4

    num2 = 8

    print(minDis(arr, num1, num2))

程序运行结果为:

2

查找数组中任何一对相等元素之间的最小距离

【中文标题】查找数组中任何一对相等元素之间的最小距离【英文标题】:Finding the minimum distance between any pair of equal elements in an array 【发布时间】:2017-05-21 20:26:58 【问题描述】:

给定一些整数数组 A = [a0, a1, ..., an],求最小距离在 ai 和 aj 之间,使得 ai = aj 和 i != j (或表示不存在这样的索引)。

所以我在 C++ 中实现了一个简单的 O(n2) 方法,包括遍历数组以寻找相等的元素并适当地更新最小距离:

#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(n2)。空间复杂度方面,除了数组/向量之外,您还必须存储地图。我到底错过了什么?

编辑: 我错误地认为 map::find 是 O(n);插入和查找操作实际上是 O(log n),即使假设使用二进制搜索之类的基本实现,也可以立即看到。

【问题讨论】:

"使用 std::map::find 来识别一个元素是否是第一次出现或不是也是 O(n)" 你确定吗?文档说:“复杂性:大小为对数。” 保持数组排序,您可以在 O(n) 时间内搜索重复项。 您的容器在搜索前是排序的还是未排序的? @arekolek 你是对的,它确实是对数的! 【参考方案1】:

我最初发布了一个与 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;

【讨论】:

【参考方案2】:

您可以将每个元素映射到它的一组索引。所以你会有类似map&lt;int, set&lt;int&gt;&gt; m 的东西,然后通过你的向量:for(int i = 0, i &lt; nums.size(); ++i) m[nums[i]].insert(i)。之后,您可以遍历地图,如果一个元素有多个索引,则找到索引之间的最小距离。应该是 O(nlog(n))。

【讨论】:

保留所有值有什么意义?将重复元素的索引与先前出现的索引进行比较就足够了。为什么O(n log n)?地图和集合都具有插入 O(1) 的平均运行时间。 @Paul (Ordered) 集合和 C++ 中的映射具有 O(log n) 操作。 C++ 还具有预期 O(1) 复杂度的无序映射。 @Paul 问题被标记为 C++,答案提到了 mapset,它们是 C++ 标准 API 中有序容器类的名称,操作复杂度为 O(log n)。

以上是关于【python】求数组中两个元素的最小距离?的主要内容,如果未能解决你的问题,请参考以下文章

基础算法 分治法求最大最小元

数组的多种用法

python array 两个数组,求他们里面元素的交集,并把这些交集的值求和

查找数组中任何一对相等元素之间的最小距离

火柴排队逆序对

用matlab如何求出一个数组中最接近某个数的两个数的下标??