ugly numbers

转载 2016年06月01日 10:09:31

Ugly Numbers

Ugly numbers are numbers whose only prime factors are 2, 3 or 5. The sequence
1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, …
shows the first 11 ugly numbers. By convention, 1 is included.
Write a program to find and print the 150’th ugly number.


We strongly recommend that you click here and practice it, before moving on to the solution.



METHOD 1 (Simple)

Thanks to Nedylko Draganov for suggesting this solution. 

Algorithm:
Loop for all positive integers until ugly number count is smaller than n, if an integer is ugly than increment ugly number count.

To check if a number is ugly, divide the number by greatest divisible powers of 2, 3 and 5, if the number becomes 1 then it is an ugly number otherwise not. 

For example, let us see how to check for 300 is ugly or not. Greatest divisible power of 2 is 4, after dividing 300 by 4 we get 75. Greatest divisible power of 3 is 3, after dividing 75 by 3 we get 25. Greatest divisible power of 5 is 25, after dividing 25 by 25 we get 1. Since we get 1 finally, 300 is ugly number.

Implementation:

# include<stdio.h>
# include<stdlib.h>
 
/*This function divides a by greatest divisible
  power of b*/
int maxDivide(int a, int b)
{
  while (a%b == 0)
   a = a/b;
  return a;
}  
 
/* Function to check if a number is ugly or not */
int isUgly(int no)
{
  no = maxDivide(no, 2);
  no = maxDivide(no, 3);
  no = maxDivide(no, 5);
   
  return (no == 1)? 1 : 0;
}   
 
/* Function to get the nth ugly number*/
int getNthUglyNo(int n)
{
  int i = 1;
  int count = 1;   /* ugly number count */
 
  /*Check for all integers untill ugly count
    becomes n*/
  while (n > count)
  {
    i++;     
    if (isUgly(i))
      count++;
  }
  return i;
}
 
/* Driver program to test above functions */
int main()
{
    unsigned no = getNthUglyNo(150);
    printf("150th ugly no. is %d ",  no);
    getchar();
    return 0;
}

This method is not time efficient as it checks for all integers until ugly number count becomes n, but space complexity of this method is O(1) 


METHOD 2 (Use Dynamic Programming)

Here is a time efficient solution with O(n) extra space. The ugly-number sequence is 1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, …
     because every number can only be divided by 2, 3, 5, one way to look at the sequence is to split the sequence to three groups as below:
     (1) 1×2, 2×2, 3×2, 4×2, 5×2, …
     (2) 1×3, 2×3, 3×3, 4×3, 5×3, …
     (3) 1×5, 2×5, 3×5, 4×5, 5×5, …

     We can find that every subsequence is the ugly-sequence itself (1, 2, 3, 4, 5, …) multiply 2, 3, 5. Then we use similar merge method as merge sort, to get every ugly number from the three subsequence. Every step we choose the smallest one, and move one step after.

Algorithm:

1 Declare an array for ugly numbers:  ugly[150]
2 Initialize first ugly no:  ugly[0] = 1
3 Initialize three array index variables i2, i3, i5 to point to 
   1st element of the ugly array: 
        i2 = i3 = i5 =0; 
4 Initialize 3 choices for the next ugly no:
         next_mulitple_of_2 = ugly[i2]*2;
         next_mulitple_of_3 = ugly[i3]*3
         next_mulitple_of_5 = ugly[i5]*5;
5 Now go in a loop to fill all ugly numbers till 150:
For (i = 1; i < 150; i++ ) 
{
    /* These small steps are not optimized for good 
      readability. Will optimize them in C program */
    next_ugly_no  = Min(next_mulitple_of_2,
                                  next_mulitple_of_3,
                                  next_mulitple_of_5); 
    if  (next_ugly_no  == next_mulitple_of_2) 
    {             
        i2 = i2 + 1;        
        next_mulitple_of_2 = ugly[i2]*2;
    } 
    if  (next_ugly_no  == next_mulitple_of_3) 
    {             
        i3 = i3 + 1;        
        next_mulitple_of_3 = ugly[i3]*3;
     }            
     if  (next_ugly_no  == next_mulitple_of_5)
     {    
        i5 = i5 + 1;        
        next_mulitple_of_5 = ugly[i5]*5;
     } 
     ugly[i] =  next_ugly_no       
}/* end of for loop */ 
6.return next_ugly_no

Example:
Let us see how it works 

initialize
   ugly[] =  | 1 |
   i2 =  i3 = i5 = 0;

First iteration
   ugly[1] = Min(ugly[i2]*2, ugly[i3]*3, ugly[i5]*5)
            = Min(2, 3, 5)
            = 2
   ugly[] =  | 1 | 2 |
   i2 = 1,  i3 = i5 = 0  (i2 got incremented ) 

Second iteration
    ugly[2] = Min(ugly[i2]*2, ugly[i3]*3, ugly[i5]*5)
             = Min(4, 3, 5)
             = 3
    ugly[] =  | 1 | 2 | 3 |
    i2 = 1,  i3 =  1, i5 = 0  (i3 got incremented ) 

Third iteration
    ugly[3] = Min(ugly[i2]*2, ugly[i3]*3, ugly[i5]*5)
             = Min(4, 6, 5)
             = 4
    ugly[] =  | 1 | 2 | 3 |  4 |
    i2 = 2,  i3 =  1, i5 = 0  (i2 got incremented )

Fourth iteration
    ugly[4] = Min(ugly[i2]*2, ugly[i3]*3, ugly[i5]*5)
              = Min(6, 6, 5)
              = 5
    ugly[] =  | 1 | 2 | 3 |  4 | 5 |
    i2 = 2,  i3 =  1, i5 = 1  (i5 got incremented )

Fifth iteration
    ugly[4] = Min(ugly[i2]*2, ugly[i3]*3, ugly[i5]*5)
              = Min(6, 6, 10)
              = 6
    ugly[] =  | 1 | 2 | 3 |  4 | 5 | 6 |
    i2 = 3,  i3 =  2, i5 = 1  (i2 and i3 got incremented )

Will continue same way till I < 150

Program:

# include<stdio.h>
# include<stdlib.h>
# define bool int
 
/* Function to find minimum of 3 numbers */
unsigned min(unsigned , unsigned , unsigned );
 
/* Function to get the nth ugly number*/
unsigned getNthUglyNo(unsigned n)
{
    unsigned *ugly =
             (unsigned *)(malloc (sizeof(unsigned)*n));
    unsigned i2 = 0, i3 = 0, i5 = 0;
    unsigned i;
    unsigned next_multiple_of_2 = 2;
    unsigned next_multiple_of_3 = 3;
    unsigned next_multiple_of_5 = 5;
    unsigned next_ugly_no = 1;
    *(ugly+0) = 1;
 
    for(i=1; i<n; i++)
    {
       next_ugly_no = min(next_multiple_of_2,
                           next_multiple_of_3,
                           next_multiple_of_5);
       *(ugly+i) = next_ugly_no;                   
       if(next_ugly_no == next_multiple_of_2)
       {
           i2 = i2+1;      
           next_multiple_of_2 = *(ugly+i2)*2;
       }
       if(next_ugly_no == next_multiple_of_3)
       {
           i3 = i3+1;
           next_multiple_of_3 = *(ugly+i3)*3;
       }
       if(next_ugly_no == next_multiple_of_5)
       {
           i5 = i5+1;
           next_multiple_of_5 = *(ugly+i5)*5;
       }
    } /*End of for loop (i=1; i<n; i++) */
    return next_ugly_no;
}
 
/* Function to find minimum of 3 numbers */
unsigned min(unsigned a, unsigned b, unsigned c)
{
    if(a <= b)
    {
      if(a <= c)
        return a;
      else
        return c;
    }
    if(b <= c)
      return b;
    else
      return c;
}
 
/* Driver program to test above functions */
int main()
{
    unsigned no = getNthUglyNo(150);
    printf("%dth ugly no. is %d ", 150, no);
    getchar();
    return 0;
}

Algorithmic Paradigm: Dynamic Programming
Time Complexity:  O(n)
Storage Complexity:  O(n)

Please write comments if you find any bug in the above program or other ways to solve the same problem.

poj-1338-Ugly Numbers

Ugly Numbers Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 20878   Accepted: 92...
  • Holyang_1013197377
  • Holyang_1013197377
  • 2014年12月04日 20:45
  • 568

UVA136 Ugly Numbers【set】

Ugly numbers are numbers whose only prime factors are 2, 3 or 5. The sequence 1, 2, 3, 4, 5, 6, 8, ...
  • tigerisland45
  • tigerisland45
  • 2016年08月06日 09:08
  • 791

N - Ugly Numbers

N - Ugly Numbers Time Limit:1000MS Memory Limit:10000KB 64bit IO Format:%lld & %llu Submit...
  • qq_32426313
  • qq_32426313
  • 2016年08月10日 08:47
  • 208

POJ1338 Ugly Numbers(解法二)【废除!!!】

问题链接:POJ1338 Ugly Numbers。基础级练习题,用C语言编写程序。 题意简述:不能被2、3和5以外的素数整除的数称为丑数,找出第1500个丑数。 问题分析:换句话说,丑数的因子只能...
  • tigerisland45
  • tigerisland45
  • 2016年08月08日 06:53
  • 599

uvaoj 136 Ugly Numbers 优先队列使用

uvaoj 136 Ugly Numbers 优先队列使用 丑数是不能被除2,3,5以外的其他素数整除的数,把丑数从小到大排列,1,2,3,4,5,6,8,9,10,12,15.......,求第1...
  • gwq5210
  • gwq5210
  • 2015年01月21日 16:45
  • 448

158ugly numbers丑数

A B C D E F G H F - Ugly Numbers Crawling in process... Crawling failed Time Limit:1000MS     Memo...
  • a716121
  • a716121
  • 2015年08月20日 15:36
  • 276

丑数Ugly Number查找算法

我们把只包含因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含因子7。习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第1500个丑数 下面是一...
  • houzengjiang
  • houzengjiang
  • 2012年09月03日 23:50
  • 8118

STL实现Ugly Numbers 注解

从阅读大佬的代码开始.. 对于我这个弱渣来说,都是精华.. 以下是对f_zyj大佬模板中提供的STL实现Ugly Numbers 学习和注解 f_zyj大佬的博客: http:...
  • zhembrace
  • zhembrace
  • 2017年05月15日 13:47
  • 208

UVA 136 - Ugly Numbers【巧用优先队列】

Ugly numbers are numbers whose only prime factors are 2, 3 or 5. The sequence 1, 2, 3, 4, 5, 6, 8, ...
  • liuke19950717
  • liuke19950717
  • 2015年11月12日 14:56
  • 328

poj 1338 Ugly Numbers【终极打表】

这道题我用的是终极打表的方法。。。。。。。。。。 哈哈哈,为了避免代码太长刷屏,把我自己的代码放到最后。。。这道题当我想到这种方法的时候哈哈大笑。。。 大家注意亮点【代码长度】: 我自己的...
  • Scythe666
  • Scythe666
  • 2013年10月28日 12:42
  • 1522
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:ugly numbers
举报原因:
原因补充:

(最多只允许输入30个字)