C 语言构造hash table 解 LC majority element问题

Leetcode上 majority element这题是 有 时间O(N), 空间O(1)的解的.

https://leetcode.com/problems/majority-element/

用hash table来解则为 时间O(N), 空间O(N). 如果是Java里 用HashMap很方便了. 有位同学问怎么用c语言来构造hash table. 我就随手写了一个:

typedef struct Node {
    int val, count;
} Node;

typedef struct HASH {
    Node *np;
    int size, capacity;
} HASH;

#define N 509

#define HASH_VAL(n) abs((n) % N)

static int ensureCapacity(HASH *hp) 
{
    int size, capacity;
    Node *np;

    size = hp->size;
    capacity = hp->capacity;
    if (size < capacity)
        return 0;
    if (capacity == 0)
        capacity = 8;
    else
        capacity <<= 1;
    np = (Node*)realloc(hp->np, capacity * sizeof(Node));
    if (np == NULL)
        return -1;
    hp->capacity = capacity;
    hp->np = np;
    return 0;
}

static void freeHashTab(HASH htab[], int n)
{
    int i;
    for (i = 0; i < n; i++)
        if (htab[i].np)
            free(htab[i].np);    
}

int majorityElement(int arr[], int n) 
{
    HASH htab[N], *hb;
    int i, j, cur, hval, res;

    memset(htab, 0, N * sizeof(HASH));
    for (i = 0; i < n; i++) {
        cur = arr[i];
        hval = HASH_VAL(cur);
        hb = &htab[hval];
        for (j = 0; j < hb->size; j++)
            if (hb->np[j].val == cur)
                break;
        if (j == hb->size) {
            if (ensureCapacity(hb) == -1)
                goto err;
            hb->np[j].val = cur;
            hb->np[j].count = 1;
            hb->size++; 
        } else {
            hb->np[j].count++;
        }
        if (hb->np[j].count > n / 2) {
            res = hb->np[j].val;
            freeHashTab(htab, N);
            return res;
        } 
    }
    
err:
    freeHashTab(htab, N);
    return -1;    
}
View Code

代码稍微长一点就肯定有bug. 这次我遇到两个问题:

1. 在给数组扩容时, 我一开始的代码是这样:

    hp->np = (Node*)realloc(hp->np, capacity * sizeof(Node));
    if (hp->np == NULL)
        return -1;

这里的问题在于, 若realloc返回NULL, 则原来的内存 不会被清除. 所以这里有一个内存泄露.

2. 需要一个hash函数 把 n映射为 [0, N - 1]. 为简单计, 我的hash函数简单的定义为:

#define N 509
#define HASH_VAL(n) (n) % N

这是不对的. 考虑 n == -1, 则hash值为-1.

再来:

#define HASH_VAL(n) abs(n) % N

貌似可以了吧. 但还是不行, 呵呵, LC上的测试用例设计的非常好. 考虑 n为-2147483648, 则abs(n) = -2147483648.

注: 2147483648超出32位int型范围, 故 abs(-2147483648) 为undefined behavior.

最后改为:

#define HASH_VAL(n) abs((n) % N)

 

posted @ 2016-03-01 23:23  brayden  阅读(265)  评论(0编辑  收藏  举报