题目
一个有序数列,序列中的每一个值都能够被2 或者3 或者5 所整除,1 是这个序列的第一个
元素。求第1500个值是多少?
思路:
首先,我们把这能被2,3,5除的一系列数叫做丑数
1)第一个丑数为1, num = 1, ugly[num++] = 1, 然后把1 * 2, 1 * 3, 1 * 5 分别添加到小顶堆中,
2)取堆顶元素x,此时x=2, num= 2,
a>若ugly[num - 1] < x,则把x加入成为第num个丑数,即ugly[num++] = x ,同时把2*x, 3 * x, 5*x加入到小顶堆中;
b>若ugly[num - 1] >= x, 则说明ugly数组中已经包含该丑数了,为了避免重复,直接跳过
3) 重复步骤1)和2),直到1500个丑数都已经找到。
一个有序数列,序列中的每一个值都能够被2 或者3 或者5 所整除,1 是这个序列的第一个
元素。求第1500个值是多少?
思路:
首先,我们把这能被2,3,5除的一系列数叫做丑数
1)第一个丑数为1, num = 1, ugly[num++] = 1, 然后把1 * 2, 1 * 3, 1 * 5 分别添加到小顶堆中,
2)取堆顶元素x,此时x=2, num= 2,
a>若ugly[num - 1] < x,则把x加入成为第num个丑数,即ugly[num++] = x ,同时把2*x, 3 * x, 5*x加入到小顶堆中;
b>若ugly[num - 1] >= x, 则说明ugly数组中已经包含该丑数了,为了避免重复,直接跳过
3) 重复步骤1)和2),直到1500个丑数都已经找到。
#include <iostream>
using namespace std;
#define NSIZ 2000
__int64 heap[NSIZ];
int heaplen;
__int64 ugly[NSIZ];
//当添加一个元素到数组末尾时,向上调整小顶堆,保证小顶堆特性:父节点值比其左右子树的值都要小
void adjustUp(__int64 heap[], int heaplen)
{
int p = heaplen, q = p / 2;
__int64 tmp = heap[heaplen];
while(q >= 1)
{
if(heap[q] < tmp)
{
break;
}
heap[p] = heap[q];
p = q;
q /= 2;
}
heap[p] = tmp;
}
//当删除堆顶元素时,最后一个元素放到堆顶,向下调节,保证小顶堆特性:父节点值比其左右子树的值都要小
void adjustDown(__int64 heap[], int heaplen)
{
__int64 tmp = heap[1];
int p = 1;
int q = 2 * p;
while(q <= heaplen)
{
if(q + 1 <= heaplen && heap[q+ 1] < heap[q])
{
++q;
}
if(heap[q] > tmp)
{
break;
}
heap[p] = heap[q];
p = q;
q *= 2;
}
heap[p] = tmp;
}
__int64 getMin(__int64 heap[], int &heaplen)
{
__int64 res = heap[1];
heap[1] = heap[heaplen--];
adjustDown(heap, heaplen);
return res;
}
void Insert(__int64 heap[], int& heaplen, __int64 key)
{
heap[++heaplen] = key;
adjustUp(heap, heaplen);
}
int main()
{
int n = 1500, i;
heaplen = 0;
ugly[1] = 1;
heap[++heaplen] = 1;
heap[++heaplen] = 2;
heap[++heaplen] = 3;
heap[++heaplen] = 5;
for (i = 2; i <= n;)
{
__int64 min = getMin(heap, heaplen);
if(min <= ugly[i-1])
{
continue;
}
ugly[i++] = min;
Insert(heap, heaplen, 2 * min);
Insert(heap, heaplen, 3 * min);
Insert(heap, heaplen, 5 * min);
}
printf("打印丑数:");
for ( i= 1;i <= n; ++i)
{
printf("%I64d ", ugly[i]);
}
return 0;
}