面试题34丑数

//======================以下为自己实现===========================

int uglyNumber(int n)
{
//int s[n]=(int*)calloc(n, sizeof(int));
int *s=(int*)calloc(n, sizeof(int));
s[0] = 1;

int count=1;
while(count < n)
{
int i=0, j=0, k=0;
for(i=0; i<count;++i)
{
if(s[i]*2 <=s[count-1])
{
continue;
}
else
{
break;
}
}

for(j=0; j<count;++j)
{
if(s[j]*3 <=s[count-1])
{
continue;
}
else
{
break;
}
}

for(k=0; k<count;++k)
{
if(s[k]*5 <=s[count-1])
{
continue;
}
else
{
break;
}
}

int min=s[i]*2;
if(s[j]*3<min)
{
min=s[j]*3;
}
if(s[k]*5<min) 
{
min=s[k]*5; 
}
s[count++] = min;
}

return s[count-1];
}
int main(int argc, char *argv[]) {
int num = uglyNumber(4);
printf("num=%d\n", num);
return 0;
}




//======================以下为转载==============================

https://blog.csdn.net/u010425776/article/details/50968521


本题详细解析均在代码注释中:

  1. /**
  2. * 题目:我们把只包含因子2、3、5的数称为丑数。求从小到大顺序第1500个丑数。习惯上把1称为第一个丑数。
  3. * @author 大闲人柴毛毛
  4. * @date 2016年3月24日
  5. */
  6. public class UglyNumber {
  7. /**
  8. * 分析:所谓“只包含因子2、3、5”其实就是只能由2、3、5相乘得到的数称为丑数。
  9. * 根据上述特性,丑数的生产过程如下:
  10. * 从1开始,分别乘以2、乘以3、乘以5,得到三个新的丑数2、3、5;
  11. * 然后再把这三个新的丑数再分别乘以2、乘以3、乘以5,得到9个丑数4、6、10、6、9、15、10、15、25;
  12. * 循环上述操作,就能源源不断地生产丑数。
  13. * 但我们发现,以上生产过程无法保证丑数按照从小到大的顺序生产,而且生产的丑数中有重复丑数。
  14. * 我们只有确保生产的丑数是有序的,才能得到第1500个丑数。因此,在生产的同时,我们需要确保当前生产的丑数都是有序的。
  15. * 过程如下:
  16. * 假设我们已经生产了n个丑数:1……N,接下来我们要生产第n+1个丑数;
  17. * 我们需要从前向后将每个丑数分别乘以2,当找到一个刚刚大于N的丑数时停下;
  18. * 然后再从1开始,从前向后将每个丑数乘以3,寻找刚刚大于N的丑数;
  19. * 同样的方法将每个丑数乘以5,寻找刚刚大于N的丑数。
  20. * 然后选出三个数中最小值,作为第N+1个丑数。
  21. * 以此类推,直到计算出1500个丑数为止。
  22. * 代码如下:
  23. */
  24. /**
  25. * 计算第n个丑数
  26. * @param n
  27. * @return 返回第n个丑数(返回-1表示程序出错)
  28. */
  29. public static int uglyNumber(int n){
  30. //若n小于0
  31. if(n<= 0){
  32. System.out.println( "n小于1!");
  33. return - 1;
  34. }
  35. //创建一个长度为n的数组
  36. int[] a = new int[n];
  37. a[ 0] = 1;
  38. //当前丑数个数
  39. int count = 1;
  40. //循环计算第n个丑数
  41. while(count<n){
  42. int i= 0,j= 0,z= 0;
  43. //从头开始分别乘以2,找到刚刚大于当前最后一个丑数时停下
  44. for(i= 0;i<a.length && a[i]* 2<=a[count- 1];i++);
  45. //从头开始分别乘以3,找到刚刚大于当前最后一个丑数时停下
  46. for(j= 0;j<a.length && a[j]* 3<=a[count- 1];j++);
  47. //从头开始分别乘以5,找到刚刚大于当前最后一个丑数时停下
  48. for(z= 0;z<a.length && a[z]* 5<=a[count- 1];z++);
  49. //找出i、j、z的最小值
  50. int min = a[i]* 2;
  51. if(a[j]* 3<min)
  52. min = a[j]* 3;
  53. if(a[z]* 5<min)
  54. min = a[z]* 5;
  55. //将最小值作为第n+1个丑数
  56. a[count++] = min;
  57. }
  58. return a[count- 1];
  59. }
  60. /**
  61. * 测试
  62. */
  63. public static void main(String[] args){
  64. System.out.println(uglyNumber( 5));
  65. }
  66. }




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值