LeetCode第347题 前K个高频元素
头铁,非要练习C语言写优先队列。
所以,就写了好久。
主要由于这道题的用例里面有负数,无法适用正常的数组下标的形式来存储elements和qp,导致引入了uthash,对数据进行hash,记录要保存的值。
但是修改过程中遗漏了两处,导致了两处bug。
学习使用uthash库函数
要思路清晰。
代码:
struct HASH_NODE{
int key;
int count; // 相当于elements
int idx; // 相当于qp,记录元素在堆里的位置。
UT_hash_handle hh;
};
struct HASH_NODE *head = NULL;
bool less(int key1, int key2){
struct HASH_NODE *node1;
HASH_FIND_INT(head, &key1, node1);
struct HASH_NODE *node2;
HASH_FIND_INT(head, &key2, node2);
// printf("key1 :%d, node1->count %d key2:%d node2->count %d\n", key1, node1->count, key2, node2->count);
return node1->count < node2->count ? true : false;
}
int size = 0;
void swap(int *pq, int i, int j)
{
int tmp = pq[i];
pq[i] = pq[j];
pq[j] = tmp;
}
void swapQp(struct HASH_NODE *tmp, int key1, int key2)
{
struct HASH_NODE *node1;
HASH_FIND_INT(head, &key1, node1);
struct HASH_NODE *node2;
HASH_FIND_INT(head, &key2, node2);
int idx = node1->idx;
node1->idx = node2->idx;
node2->idx = idx;
}
void swim(int *pq, struct HASH_NODE *tmp, int idx)
{
while (idx / 2 >= 1 && less(pq[idx], pq[idx / 2])) {
swap(pq, idx, idx / 2);
swapQp(tmp, pq[idx], pq[idx / 2]);
idx /= 2;
}
}
void sink(int *pq, int len, struct HASH_NODE *tmp, int idx)
{
while (idx * 2 <= len) {
int i = idx * 2;
if (i < len && less(pq[i + 1], pq[i])) {
i++;
}
if (!less(pq[i], pq[idx])) break; // bug3 大小于之间思路不清晰,导致问题。
swap(pq, idx, i);
swapQp(tmp, pq[idx], pq[i]);
idx = i;
}
}
void insert(int *pq, int k, int item, struct HASH_NODE *tmp)
{
size++;
pq[size] = item;
tmp->idx = size;
swim(pq, tmp, size);
}
void deleteAll() {
struct HASH_NODE *cur_node, *tmp;
HASH_ITER(hh, head, cur_node, tmp) {
HASH_DEL(head, cur_node);
free(cur_node);
}
}
void createPq(int *pq, int k, int item)
{
struct HASH_NODE *tmp;
HASH_FIND_INT(head, &item, tmp);
if (tmp == NULL) {
struct HASH_NODE *add = malloc(sizeof(struct HASH_NODE));
add->key = item;
add->count = 1;
add->idx = 0;
HASH_ADD_INT(head, key, add);
tmp = add;
} else {
tmp->count++;
}
if (tmp->idx == 0) {
if (size < k) {
insert(pq, k, item, tmp);
} else if (less(pq[1], item)) {
struct HASH_NODE *pqOne; // bug2 这里是删除根元素,但是要将idx置0。
HASH_FIND_INT(head, &pq[1], pqOne);
pqOne->idx = 0;
pq[1] = item;
tmp->idx = 1;
sink(pq, size, tmp, 1);
}
} else {
swim(pq, tmp, tmp->idx);
sink(pq, size, tmp, tmp->idx);
}
}
int* topKFrequent(int* nums, int numsSize, int k, int* returnSize)
{
int *res = malloc(sizeof(int) * (k + 1));
memset(res, 0, sizeof(int) * k);
if (numsSize <= k) {
memcpy(res, nums, numsSize * sizeof(int));
*returnSize = k;
return res;
}
head = NULL;
size = 0; // bug1 由于leetcode自身是连跑的,所以中间使用的全局变量一定要清零。
// 构造优先级队列
for (int i = 0; i < numsSize; i++) {
createPq(res, k, nums[i]);
}
deleteAll(); // hash表的资源也要释放
res[0] = res[k];
*returnSize = k;
return res;
}