LeetCode第347题 前K个高频元素

本文博主分享了在C语言中使用uthash库解决LeetCode第347题的过程,重点讲解了如何构建优先队列并处理负数元素,以及修复的两个关键bug。通过实际代码展示了如何使用优先队列找到前k个高频元素的思路和实现技巧。
摘要由CSDN通过智能技术生成

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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值