文章目录

  • 一、题目
    • 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(klog2​k)。

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;

三、本题小知识

  堆 是一棵完全二叉树。


四、加群须知

  相信看我文章的大多数都是「 大学生 」,能上大学的都是「 精英 」,那么我们自然要「 精益求精 」,如果你还是「 大一 」,那么太好了,你拥有大把时间,当然你可以选择「 刷剧 」,然而,「 学好算法 」,三年后的你自然「 不能同日而语 」
  那么这里,我整理了「 几十个基础算法 」 的分类,点击开启:

⭐算法入门⭐《堆》中等01 —— LeetCode 面试题 17.09. 第 k 个数相关推荐

  1. leetcode 面试题 17.14. 最小K个数 大顶堆 小顶堆 快排

    leetcode 面试题 17.14. 最小K个数 [难度:中等] 设计一个算法,找出数组中最小的k个数.以任意顺序返回这k个数均可. 示例: 输入: arr = [1,3,5,7,2,4,6,8], ...

  2. 面试题 17.09. 第 k 个数[小顶堆][动态规划]

    思路 暴力搜索 因为要求的数只含3\5\7这三个素因子,因此只需判断将每个数除3/5/7除尽后是否为1,从而判断是不是所要求序列中的一个数. 超时 代码如下: class Solution {publ ...

  3. 程序员面试金典 - 面试题 17.09. 第 k 个数(set优先队列/DP)

    1. 题目 有些数的素因子只有 3,5,7,请设计一个算法找出第 k 个数. 注意,不是必须有这些素因子,而是必须不包含其他的素因子. 例如,前几个数按顺序应该是 1,3,5,7,9,15,21. 示 ...

  4. 力扣 面试题 17.09. 第 k 个数

    题目 有些数的素因子只有 3,5,7,请设计一个算法找出第 k 个数.注意,不是必须有这些素因子,而是必须不包含其他的素因子.例如,前几个数按顺序应该是 1,3,5,7,9,15,21. 示例 输入: ...

  5. 面试题 17.14. 最小K个数

    面试题 17.14. 最小K个数 设计一个算法,找出数组中最小的k个数.以任意顺序返回这k个数均可. 示例: 输入: arr = [1,3,5,7,2,4,6,8], k = 4 输出: [1,2,3 ...

  6. 【每日一题】 面试题 17.14. 最小K个数

    面试题 17.14. 最小K个数

  7. LeetCode:面试题40. 最小的k个数

    40. 最小的k个数 题目: 解题思路: 源码: 题目: 解题思路: 1.快速排序: 2.堆排序: 详细解释看leetcode的官网 源码: int comp(void *a,void *b){int ...

  8. 程序员面试金典 - 面试题 17.14. 最小K个数(快排划分O(n))

    1. 题目 设计一个算法,找出数组中最小的k个数.以任意顺序返回这k个数均可. 示例: 输入: arr = [1,3,5,7,2,4,6,8], k = 4 输出: [1,2,3,4]提示: 0 &l ...

  9. 力扣 面试题 17.14. 最小K个数

    题目 设计一个算法,找出数组中最小的k个数.以任意顺序返回这k个数均可. 示例 输入: arr = [1,3,5,7,2,4,6,8], k = 4 输出: [1,2,3,4] 来源:力扣(LeetC ...

最新文章

  1. R语言dplyr包移除dataframe数据列实战(Remove Columns)
  2. oracle跨库 导库,Oracle 用dblink 跨库导数据
  3. 【20161109】noip模拟赛
  4. Oracle常用操作之登录名和密码大小写问题
  5. ABAP 7.4 新语法-内嵌生命和内表操作
  6. 关于地图制图大赛的8点说明,附地图学习资源
  7. pythonwin1064位_在Windows 10 64位中安装Matplotlib
  8. 伪原创方法-学习一下
  9. Node.js调用百度地图Web服务API的Geocoding接口进行点位反地理信息编码
  10. 1.1集成电路设计基础
  11. python写TCP协议
  12. c语言sqart函数格式,2019-07-29 复习C语言入门知识
  13. 零基础学HTML5的学习路线完整版
  14. 3d建模师就业前景?
  15. Linux vim分屏,如何切换窗口
  16. 大数据局数据安全建设实践案例汇编
  17. 基于springboot的电影院管理系统
  18. JSON压缩:JSONMinify
  19. 网络营销中的博客营销有什么价值?对于博客营销我们应该注意哪些问题?
  20. 好看轻量级北邮人导航源码

热门文章

  1. 市面上有哪几种门_卧室门怎么选?市面上5种常见房门大揭秘
  2. 云计算 python PXE+KS无人值守安装
  3. Unity实现刀光特效
  4. Pyinstaller将yolov5的detect.py封装成detect.exe,并用C++调用
  5. Linux入门和使用
  6. 基于Pytorch的强化学习(DQN)之 Experience Replay
  7. 空间换时间——为字符串排序
  8. 机器人学的数理基础知识
  9. [生而为人-思考] Knowledge Cooking -3rd 分享会记录
  10. 进程互斥以及进程互斥实现方法(包含代码)