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; }
代码稍微长一点就肯定有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)
时间: 2024-10-11 01:41:57