查找重复项的最快方法

时间:2016-04-13 04:40:28

标签: c arrays algorithm duplicates

所以我的面试官给我看了以下代码,

struct test {
    uint8_t inuse;
    int32_t val;
};

#define MAX_LIST_SIZE 100
struct test list[MAX_LIST_SIZE];

int checkAndAdd(int32_t val) {
    for(int i=0; i<MAX_LIST_SIZE; i++) {
        if(list[i].inuse && list[i].value == value)
            return DUPLICATE;
    }
    for(int i=0; i<MAX_LIST_SIZE; i++) {
        if(!list[i].inuse) {
            list[i].inuse = 1;
            list[i].value = value;
            return ADDED;
        }
    }
    return EA_FAIL;
}

并问我以下问题。

  1. 如何更快地完成该功能?
  2. 在数组中查找重复项的其他最快方法是什么?
  3. 我的回答是 1.

    int checkAndAdd(int32_t val) {
        int32_t addedIndex = -1;
    
        for(int i=0; i<MAX_LIST_SIZE; i++) {
            if(list[i].inuse && list[i].value == value) {
                if (addedIndex != -1) {
                    list[addedIndex].inuse = 0;
                    list[addedIndex].value = 0;
                }
                return DUPLICATE;
            } else if (!list[i].inuse && (addedIndex == -1)) {
                list[i].inuse = 1;
                list[i].value = value;
                addedIndex = i;
            }
        }
        if (addedIndex)
            return ADDED;
    
        return EA_FAIL;
    }
    
    1. 你不能比O(n)更快地重复检查。
    2. 我的答案是否正确?请建议任何其他好方法并回答2.谢谢。

3 个答案:

答案 0 :(得分:2)

它在某种程度上依赖于数据模式,但插值搜索是O(log log n)。

使用二进制搜索可以得到O(log n),对于n <= 100,最多可以有7个搜索步骤,这使得插值搜索可能不值得。

编辑添加旁注:好奇structint32_t,但函数的参数是普通int。可能没有损坏(那里有没有任何ILP64系统?),但似乎有点草率。

答案 1 :(得分:2)

如果您需要能够快速插入,删除和避免重复:您想要的是set可能使用hash table实现,其中键和值都指向相同的数据。

哈希表本身不能有重复项。对于插入,删除和查找以及空间上的O(n),它们平均 O(1)。唯一的缺点是价值没有固有的顺序。由于您的原始代码似乎没有保留完好无损的订单。

答案 2 :(得分:1)

如果我作为面试问题给你这个我可能想讨论Hashes等,这将是一个好兆头,哈希是基本的数据结构,但我真的想看看你是否可以合并这两个循环而你做过某事。对于重复检查,您的第二个答案对于列表是正确的,即O(n),但通常是不正确的,因为它依赖于数据结构,如果您使用哈希它是O(1)。

请注意,在现实生活中,O(1)有时甚至经常会比O(n)更慢,即当你为了获得密钥而进行哈希处理,完成查找并遍历列表时您可能在链接列表中找到的5个哈希结构中找到了单个项目。