⭐算法入门⭐《堆》中等01 —— LeetCode 面试题 17.09. 第 k 个数
文章目录
- 一、题目
- 1、题目描述
- 2、基础框架
- 3、原题链接
- 二、解题报告
- 1、思路分析
- 2、时间复杂度
- 3、代码详解
- 三、本题小知识
- 四、加群须知
一、题目
1、题目描述
有些数的素因子只有 3,5,7,请设计一个算法找出第 k 个数。注意,不是必须有这些素因子,而是必须不包含其他的素因子。例如,前几个数按顺序应该是 1,3,5,7,9,15,21。
样例输入:k = 5
样例输出:9
2、基础框架
- C语言 版本给出的基础框架代码如下:
int getKthMagicNumber(int k){}
3、原题链接
面试题 17.09. 第 k 个数
二、解题报告
1、思路分析
初始情况下只有一个 1,然后将它入堆。这时候,堆顶元素就是第 1 个素因子只有 3、5、7 的数,将这个数乘上 3、乘上 5、乘上 7 的三个数塞入堆中,继续弹出下一个数,每弹出一个,就塞入三个,相当于一次操作多两个数,直到第 kkk 个数结束。
2、时间复杂度
将所有元素塞入堆的过程就是最坏时间复杂度,为 O(klog2k)O(klog_2k)O(klog2k)。
3、代码详解
/**********************************小顶堆模板************************************/
#define lson(idx) (idx << 1|1)
#define rson(idx) ((idx + 1) << 1)
#define parent(idx) ((idx - 1) >> 1)
#define root 0
#define DataType long long// -1 和 1 交换,就变成了大顶堆
int compareData(const DataType* a, const DataType* b) {if(*a < *b) {return -1;}else if(*a > *b) {return 1;}return 0;
}
void swap(DataType* a, DataType* b) {DataType tmp = *a;*a = *b;*b = tmp;
}typedef struct {DataType *data;int size;int capacity;
}Heap;// 内部接口,小写驼峰// heapShiftDown 这个接口是一个内部接口,所以用小写驼峰区分,用于对堆中元素进行删除的时候的下沉调整;
void heapShiftDown(Heap* heap, int curr) {int son = lson(curr);while(son < heap->size) {if( rson(curr) < heap->size ) {if( compareData( &heap->data[rson(curr)], &heap->data[son] ) < 0 ) {son = rson(curr); // 始终选择值更小的结点} }if( compareData( &heap->data[son], &heap->data[curr] ) < 0 ) {swap(&heap->data[son], &heap->data[curr]); // 子结点的值小于父结点,则执行交换;curr = son;son = lson(curr);}else {break; // 子结点的值大于父结点,说明已经正确归位,下沉操作结束,跳出循环;}}
}// heapShiftUp 这个接口是一个内部接口,所以用小写驼峰区分,用于对堆中元素进行插入的时候的上浮调整;
void heapShiftUp(Heap* heap, int curr) {int par = parent(curr);while(par >= root) {if( compareData( &heap->data[curr], &heap->data[par] ) < 0 ) {swap(&heap->data[curr], &heap->data[par]); // 子结点的值小于父结点,则执行交换;curr = par;par = parent(curr);}else {break; // 子结点的值大于父结点,说明已经正确归位,上浮操作结束,跳出循环;}}
}bool heapIsFull(Heap *heap) {return heap->size == heap->capacity;
}// 外部接口,大写驼峰// 堆的判空
bool HeapIsEmpty(Heap *heap) {return heap->size == 0;
}// 堆的插入
// 插到最后一个位置,然后不断进行上浮操作
bool HeapPush(Heap* heap, DataType data) {if( heapIsFull(heap) ) {return false;}heap->data[ heap->size++ ] = data;heapShiftUp(heap, heap->size-1);return true;
}// 堆的删除
// 1、删除堆顶元素时,将堆底部的下标最大的元素放入对顶;
// 2、然后调用 shiftDown 将这个元素进行下沉操作;
// 对于小顶堆来说,从根到叶子的路径必然是单调不降的,所以下沉操作一定会终止在路径的某个点,并且保证所有的堆路径还是能够维持单调不降;
bool HeapPop(Heap *heap) {if(HeapIsEmpty(heap)) {return false;}heap->data[root] = heap->data[ --heap->size ];heapShiftDown(heap, root);return true;
}DataType HeapTop(Heap *heap) {assert(!HeapIsEmpty(heap));return heap->data[root];
}// 创建堆
Heap* HeapCreate(DataType *data, int dataSize, int maxSize) {int i;Heap *h = (Heap *)malloc( sizeof(Heap) );h->data = (DataType *)malloc( sizeof(DataType) * maxSize );h->size = 0;h->capacity = maxSize;for(i = 0; i < dataSize; ++i) {HeapPush(h, data[i]);}return h;
}// 销毁堆
void HeapFree(Heap *heap) {free(heap->data);free(heap);
}/**********************************小顶堆模板************************************/DataType d[1000001];void PushValue(Heap *h, long long v) { // (1)if(v < (long long)1<<32)HeapPush(h, v);elseHeapPush(h, ((long long)1<<32) - 1);
}int getKthMagicNumber(int k){Heap *h = HeapCreate(NULL, 0, 30000); // (2)DataType val;HeapPush(h, 1); // (3)while(k--) {val = HeapTop(h); // (4)HeapPop(h);while(!HeapIsEmpty(h)) { // (5)if(HeapTop(h) == val) {HeapPop(h);}else {break;}}if(k == 0) {HeapFree(h);return val; // (6)}PushValue(h, (long long)val * 3); // (7)PushValue(h, (long long)val * 5); // (8)PushValue(h, (long long)val * 7); // (9)}return 0;
}
- (1)(1)(1) 这个接口代表往堆中插入一个数 vvv,如果 vvv 超过 INT32 范围,则插入 INT32 的最大值;
- (2)(2)(2) 创建一个空堆;
- (3)(3)(3) 往堆中插入初始元素 1;
- (4)(4)(4) 去除对顶元素;
- (5)(5)(5) 去重;
- (6)(6)(6) 当取到第 kkk 个不同元素时返回;
- (7)(7)(7) 往堆中插入 val * 3;
- (8)(8)(8) 往堆中插入 val * 5;
- (9)(9)(9) 往堆中插入 val * 7;
三、本题小知识
堆 是一棵完全二叉树。
四、加群须知
相信看我文章的大多数都是「 大学生 」,能上大学的都是「 精英 」,那么我们自然要「 精益求精 」,如果你还是「 大一 」,那么太好了,你拥有大把时间,当然你可以选择「 刷剧 」,然而,「 学好算法 」,三年后的你自然「 不能同日而语 」。
那么这里,我整理了「 几十个基础算法 」 的分类,点击开启:
leetcode 面试题 17.14. 最小K个数 [难度:中等] 设计一个算法,找出数组中最小的k个数.以任意顺序返回这k个数均可. 示例: 输入: arr = [1,3,5,7,2,4,6,8], ... 思路 暴力搜索 因为要求的数只含3\5\7这三个素因子,因此只需判断将每个数除3/5/7除尽后是否为1,从而判断是不是所要求序列中的一个数. 超时 代码如下: class Solution {publ ... 1. 题目 有些数的素因子只有 3,5,7,请设计一个算法找出第 k 个数. 注意,不是必须有这些素因子,而是必须不包含其他的素因子. 例如,前几个数按顺序应该是 1,3,5,7,9,15,21. 示 ... 题目 有些数的素因子只有 3,5,7,请设计一个算法找出第 k 个数.注意,不是必须有这些素因子,而是必须不包含其他的素因子.例如,前几个数按顺序应该是 1,3,5,7,9,15,21. 示例 输入: ... 面试题 17.14. 最小K个数 设计一个算法,找出数组中最小的k个数.以任意顺序返回这k个数均可. 示例: 输入: arr = [1,3,5,7,2,4,6,8], k = 4 输出: [1,2,3 ... 面试题 17.14. 最小K个数 40. 最小的k个数 题目: 解题思路: 源码: 题目: 解题思路: 1.快速排序: 2.堆排序: 详细解释看leetcode的官网 源码: int comp(void *a,void *b){int ... 1. 题目 设计一个算法,找出数组中最小的k个数.以任意顺序返回这k个数均可. 示例: 输入: arr = [1,3,5,7,2,4,6,8], k = 4 输出: [1,2,3,4]提示: 0 &l ... 题目 设计一个算法,找出数组中最小的k个数.以任意顺序返回这k个数均可. 示例 输入: arr = [1,3,5,7,2,4,6,8], k = 4 输出: [1,2,3,4] 来源:力扣(LeetC ...⭐算法入门⭐《堆》中等01 —— LeetCode 面试题 17.09. 第 k 个数相关推荐
最新文章
热门文章