LeetCode·每日一题·895.最大频率栈·哈希+辅助栈

作者:小迅
链接:https://leetcode.cn/problems/maximum-frequency-stack/solutions/1998847/by-xun-ge-v-awcf/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 

题目

 

示例

 

思路

题目需要我们每一次 pop 的时候返回出现频率最大的元素

对于需要记录任意一个数出现多少次使用哈希表无疑是比较方便的,并且查找和维护都是非常方便的,然后插入一个元素就对哈希表进行排序,将出现次数最多的元素排到前面,每次pop的时候就将哈希表头节点弹出,但是这里存在一个问题,当我们存在相同的出现次数时,我们需要选择最近入栈的元素,所有还需要在哈希中记录我们的入栈顺序,当出现次数相同时取最先入栈的元素,但是这样会超时,原因是每插入一个元素就需要排序一次,存在很多次重复排序操作。

优化 使用哈希记录出现次数这个肯定是最优的,那么就需要优化入栈顺序,那么我们直接使用栈来记录顺序,并且始终保存出现次数最多的元素位于栈顶,当需要弹出元素时,只需要弹出栈顶元素即可。那么应该怎么记录呢,我们可以开辟多个栈,每个栈记录相同出现次数的元素的入栈顺序,每次出栈时,只需要取最大出现次数的栈的栈顶即可。

具体实现看代码,注释超级详细

代码

//哈希+辅助栈
struct my_struct {
    int id;                    /* key */
    int count;
    UT_hash_handle hh;         /* makes this structure hashable */
};//哈希结构

typedef struct {
    struct my_struct *users;//哈希表头
    int *ans[200001];//多个辅助栈
    int index;//最大出现次数值
    int *top;//每个栈的栈顶值
} FreqStack;


FreqStack* freqStackCreate() {
    FreqStack* obj = (FreqStack *)malloc(sizeof(FreqStack));
    obj->users = NULL;
    obj->top = (int *)malloc(sizeof(int) * 200001);
    memset(obj->top, 0, sizeof(int) * 200001);
    obj->index = 0;//初始化变量,栈的初始化当有元素时再申请
    return obj;
}

void freqStackPush(FreqStack* obj, int val) {
    struct my_struct *s = NULL;
    HASH_FIND_INT(obj->users, &val, s);  /* id already in the hash? */
    if (s == NULL) {//当前元素在哈希表中不存在
        s = (struct my_struct*)malloc(sizeof(struct my_struct));
        s->id = val;//创建哈希节点
        s->count = 1;
        HASH_ADD_INT(obj->users, id, s);  /* id is the key field *///加入哈希表
    } else {//存在修改出现次数
        ++s->count;
    }
    
    if (s->count > obj->index) {//每次都记录最大出现次数
        obj->index = s->count;
        obj->ans[s->count] = malloc(sizeof(int) * 200001);
    }
    obj->ans[s->count][obj->top[s->count]++] = val;//入栈
    return;
}



int freqStackPop(FreqStack* obj) {
    int val = obj->ans[obj->index][--obj->top[obj->index]];//出栈,每次出最大出现次数栈的栈顶即可
    if (obj->top[obj->index] == 0) {//判断当前栈是否为空
        free(obj->ans[obj->index]);//为空释放空间,防止内存泄漏
        obj->ans[obj->index] = NULL;
        --obj->index;
    }
    struct my_struct *s = NULL;
    HASH_FIND_INT(obj->users, &val, s);  /* id already in the hash? */
    --s->count;//将对于元素出现次数 -1
    return val;
}

void freqStackFree(FreqStack* obj) {
    struct my_struct *current_user;//销毁
    struct my_struct *tmp;
    HASH_ITER(hh, obj->users, current_user, tmp) {
        HASH_DEL(obj->users, current_user);  /* delete it (users advances to next) */
        free(current_user);             /* free it */
    }
    for (int i = 1; i <= obj->index; ++i) {
        free(obj->ans[i]);
        obj->ans[i] = NULL;
    }
    free(obj->top);
    obj->top;
    free(obj);
    obj = NULL;
    return ;
}

/**
 * Your FreqStack struct will be instantiated and called as such:
 * FreqStack* obj = freqStackCreate();
 * freqStackPush(obj, val);
 
 * int param_2 = freqStackPop(obj);
 
 * freqStackFree(obj);
*/


作者:小迅
链接:https://leetcode.cn/problems/maximum-frequency-stack/solutions/1998847/by-xun-ge-v-awcf/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

class FreqStack {
    unordered_map<int, int> cnt;
    vector<stack<int>> stacks;
public:
    void push(int val) {
        if (cnt[val] == stacks.size()) // 这个元素的频率已经是目前最多的,现在又出现了一次
            stacks.push_back({}); // 那么必须创建一个新栈
        stacks[cnt[val]].push(val);
        ++cnt[val]; // 更新频率
    }

    int pop() {
        int val = stacks.back().top(); // 弹出最右侧栈的栈顶
        stacks.back().pop();
        if (stacks.back().empty()) // 栈为空
            stacks.pop_back(); // 删除
        --cnt[val]; // 更新频率
        return val;
    }
};

/**
 * Your FreqStack object will be instantiated and called as such:
 * FreqStack* obj = new FreqStack();
 * obj->push(val);
 * int param_2 = obj->pop();
 */

作者:小迅
链接:https://leetcode.cn/problems/maximum-frequency-stack/solutions/1998847/by-xun-ge-v-awcf/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
//超时版,只使用哈希,每插入一个元素就需要排序一次,存在很多重复排序操作
typedef struct mylist {
    int index;
    struct mylist *next;
}mylist;

struct my_struct {
    int id;                    /* key */
    int count;
    mylist * node;
    UT_hash_handle hh;         /* makes this structure hashable */
};

typedef struct {
    struct my_struct *users;
    int index;
} FreqStack;


FreqStack* freqStackCreate() {
    FreqStack* obj = (FreqStack *)malloc(sizeof(FreqStack));
    obj->users = NULL;
    obj->index = 0;
    return obj;
}
int com(const struct my_struct *_a, const struct my_struct *_b) 
{
    return (_a->count == _b->count) ? (_b->node->index - _a->node->index) : (_b->count - _a->count);
} 
void freqStackPush(FreqStack* obj, int val) {
    struct my_struct *s = NULL;
    HASH_FIND_INT(obj->users, &val, s);  /* id already in the hash? */
    if (s == NULL) {
        s = (struct my_struct*)malloc(sizeof(struct my_struct));
        s->node = (mylist *)malloc(sizeof(mylist));
        s->node->index = obj->index;
        s->node->next = NULL;
        s->id = val;
        s->count = 1;
        HASH_ADD_INT(obj->users, id, s);  /* id is the key field */
    } else {
        mylist *node = (mylist *)malloc(sizeof(mylist));
        node->index = obj->index;
        node->next = s->node;
        s->node = node;
        ++s->count;
    }
    ++obj->index;
    return;
}



int freqStackPop(FreqStack* obj) {
    HASH_SORT(obj->users, com);
    int val = obj->users->id;
    --obj->users->count;
    obj->users->node = obj->users->node->next;
    if (obj->users->count == 0) {
        struct my_struct *user = obj->users;
        HASH_DEL(obj->users, user);  /* user: pointer to deletee */
        free(user);
    }
    return val;
}

void freqStackFree(FreqStack* obj) {
    struct my_struct *current_user;
    struct my_struct *tmp;
    HASH_ITER(hh, obj->users, current_user, tmp) {
        HASH_DEL(obj->users, current_user);  /* delete it (users advances to next) */
        free(current_user);             /* free it */
    }
    free(obj);
    obj = NULL;
    return ;
}

/**
 * Your FreqStack struct will be instantiated and called as such:
 * FreqStack* obj = freqStackCreate();
 * freqStackPush(obj, val);
 
 * int param_2 = freqStackPop(obj);
 
 * freqStackFree(obj);
*/

作者:小迅
链接:https://leetcode.cn/problems/maximum-frequency-stack/solutions/1998847/by-xun-ge-v-awcf/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值