leetcood_347 C语言

news/2024/11/22 21:20:25/
  1. 题目描述:给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按任意顺序 返回答案。

  2. 示例
    输入: nums = [1,1,1,2,2,3], k = 2
    输出: [1,2]

    输入: nums = [1], k = 1
    输出: [1]

  3. 提示

    1 <= nums.length <= 105

    k 的取值范围是 [1, 数组中不相同的元素的个数],题目数据保证答案唯一,换句话说,数组中前 k 个高频元素的集合是唯一的

  4. 前 K 个高频元素

  5. (方法一)解题思路:
    (1)将每一个数组nums元素放进哈希表中,以元素值作为键,并为每个元素出现次数计数;
    (2)给节点排序,uthash库中包含了哈希表的查询、插入、删除和排序等功能,包含的 HASH_SORT 函数可以根据key或者count值对哈希表的内容进行排序。本题应当依据count值进行从大到小排序,最后依次输出前k个哈希表的key值。

  6. (方法一)代码:

/*** Note: The returned array must be malloced, assume caller calls free().*/
struct hash_table {int ikey;    // 键值nums[i]int count;  // 计数UT_hash_handle hh;
};
struct hash_table *h;
struct hash_table* find(int ikey)
{struct hash_table *s = NULL;HASH_FIND_INT(h,&ikey,s);return s;
}
void insert(int ikey)
{struct hash_table *s = find(ikey);if(s==NULL){s = (struct hash_table*)malloc(sizeof(struct hash_table));  s->ikey = ikey;  s->count = 1;HASH_ADD_INT(h, ikey, s);}else{s->count++;}
}
// 类似于qsort函数里的cmp函数,确定排序是从大到小还是从小到大
int count_sort(struct hash_table *a, struct hash_table *b) {return (b->count - a->count);//依据count值从大到小排序
}int* topKFrequent(int* nums, int numsSize, int k, int* returnSize){*returnSize = k;h = NULL;for(int i=0;i<numsSize;i++){insert(nums[i]);}int *ret = (int*)malloc(sizeof(int)*k);// 对哈希表依据count值进行排序HASH_SORT(h, count_sort);struct hash_table *s;int index = 0;for(s = h;index < k; s = s->hh.next) {ret[index++] = s->ikey;}return ret;
}
  1. 时间复杂度?空间复杂度?
  2. (方法二)解题思路:
    (1)将每一个数组nums元素放进哈希表中,以元素值作为键,并为每个元素出现次数计数;
    (2)建立大小为 k 的小顶堆,比较后续元素和堆顶元素count值,如果后续元素比较大,则将堆顶元素替换成新元素值,将替换后的堆进行小顶堆的筛选,保证堆顶元素的最小的(中间元素不一定非要严格按照从小到大排序)。
  3. (方法二)代码:
/*** Note: The returned array must be malloced, assume caller calls free().*/// 时间复杂度:O(Nlogk)// 空间复杂度:O(N)
struct hash_table {int ikey;    // 键值nums[i]int count;  // 计数UT_hash_handle hh;
};
struct pairs{int val;int count;
};
struct pairs *heap;
struct hash_table *h;
// 哈希表的插入函数
void insert(int ikey)
{struct hash_table *s = NULL;HASH_FIND_INT(h,&ikey,s);if(s==NULL){s = (struct hash_table*)malloc(sizeof(struct hash_table));  s->ikey = ikey;  s->count = 1;HASH_ADD_INT(h, ikey, s);}else{s->count++;}
}
// 交换
void swap(struct pairs* i, struct pairs* j)
{struct pairs temp = *i;*i = *j;*j = temp;
}
// 建立小顶堆的过程,最顶上的元素一定是最小的
void build_little_heap(int start,int end)
{for (int index = 2 * start + 1;index <= end;index=2* index+1){if (index < end && heap[index].count > heap[index + 1].count){index++;}if (heap[start].count <= heap[index].count){break;}swap(heap + start, heap + index);start = index;}
}int* topKFrequent(int* nums, int numsSize, int k, int* returnSize){*returnSize = k;h = NULL;for(int i=0;i<numsSize;i++){insert(nums[i]);}heap = (struct pairs*)malloc(sizeof(struct pairs)*(k+1));int *heapSize = malloc(sizeof(int));*heapSize = 0;struct hash_table *s,*tmp;// HASH_ITER(hh, h, s, tmp)for (s = h; s != NULL; s = s->hh.next){if(*heapSize >= k)  // 元素数目超过小顶堆元素数目,需要将堆顶元素弹出,替换成要加进去的元素{struct pairs tmp = heap[0];if(tmp.count < s->count){heap[0].val = s->ikey;heap[0].count = s->count;for(int i=*heapSize/2-1;i>=0;i--)//重复建立小顶堆的过程,保证堆顶元素最小{build_little_heap(i,*heapSize-1);}}}else// 元素数目不超过小顶堆元素数目,将元素 放入堆底{heap[*heapSize].val = s->ikey;heap[(*heapSize)++].count = s->count;for(int i=*heapSize/2-1;i>=0;i--){build_little_heap(i,*heapSize-1);//重复建立小顶堆的过程,保证堆顶元素最小}}}int* ret = (int*)malloc(sizeof(int)*k);for(int i=0;i<k;i++){ret[i] = heap[i].val;}return ret;
}

http://www.ppmy.cn/news/551937.html

相关文章

第 347 场周赛

A 移除字符串中的尾随零 模拟 class Solution { public:string removeTrailingZeros(string num) {while(num.back()0)num.pop_back();return num;} };B 对角线上不同值的数量差 还是模拟… class Solution { public:vector<vector<int>> differenceOfDistinc…

算法day 13|239,347

今日内容&#xff1a; 239. 滑动窗口最大值 347.前 K 个高频元素 总结 239. 滑动窗口最大值 &#xff08;一刷至少需要理解思路&#xff09; class Myqueue(object):def __init__(self):self.queue deque()#保留队列最大的元素在队列里面&#xff0c;其他都pop掉def push(sel…

【C++核心】函数的应用和提高详解

一. 函数 1.1 概述 作用&#xff1a; 将一段经常使用的代码封装起来&#xff0c;减少重复代码。一个较大的程序&#xff0c;一般分为若干个程序块&#xff0c;每个模块实现特定的功能。 1.2 函数的定义 函数的定义一般主要有5个步骤&#xff1a; 1、返回值类型 2、函数名 3…

从零开始理解Linux中断架构(7)--- Linux执行上下文之中断上下文

1 中断处理程序的基本要求 当前运行的loop是一条执行流,中断程序运行开启了另外一条执行流,从上一节得知这是三种跳转的第三类,这个是一个大跳转。对中断程序的基本要求就是中断执行完毕后要恢复到原来执行的程序,除了时间流逝外,原来运行的程序应该毫无感知。 具体到Armv…

【工具】Spring 历史官方文档理解(持续更新)

文章目录 [1] Spring Framework 5.2.24CoreAOP 概念AspectJoin pointAdvicePointcutIntroductionTarget objectAOP proxyWeaving Spring AOPAspectJ官方 demo 学习 Pointcut 表达式官方 demo 学习 Advice 声明官方 demo 学习 Introductions &#xff08;接口拓展&#xff09;AO…

5.2.3目录与文件之权限意义

现在我们知道了Linux系统内文件的三种身份&#xff08;拥有者、群组与其他人&#xff09;&#xff0c;知道每种身份都有三种权限&#xff08;rwx&#xff09;&#xff0c; 已知道能够使用chown, chgrp, chmod去修改这些权限与属性&#xff0c;当然&#xff0c;利用ls -l去观察文…

C语言倒计时器

今天用这几天所学知识自己编写一个简易计时器&#xff08;因为过于简单&#xff0c;所以不过多解释&#xff09; #include<stdio.h> #include<Windows.h>//编写一个倒计时器void main() {system("title 倒计时器");//设置标题system("mode con col…

51单片机实现倒计时,按键控制倒计时

基于AT89C52的答辩倒计时。四个按键分别控制倒计时开始&#xff0c;暂停&#xff0c;时间加和减。剩下30S时蜂鸣器响&#xff0c;倒计时结束蜂鸣器响。 #include <REGX52.H>unsigned char min1; unsigned char sec00; sbit KEY1P3^1; sbit KEY2P3^0; sbit KEY3P3^2; sbit…