30.丑数

丑数

题目描述

把只包含因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。
这道题有两个版本,一个是简单版,这个版本思路非常简单,但是时间复杂度高,无法过关。
简单版代码如下:
class Solution {
public:
    int GetUglyNumber_Solution(int index) {
    	if ( index <= 0 )  return 0 ;
        
        int count = 0 ;
        int sumOfUgly = 0 ;
        while ( sumOfUgly <= index ) {
            count += 1 ;
            if ( isUgly( count ) ) {
                sumOfUgly++ ;
            }
        }
        return count ;
    }
    
    bool isUgly( int n ) {
        while ( n % 2 == 0 ) {
            n /= 2 ;
        }
        while ( n % 3 == 0 ) {
            n /= 3 ;
        }
        while ( n % 5 == 0 ) {
            n /= 5 ;
        }
        return n == 1 ? true : false ;
    }
};
复杂版就要用指针控制了,其实思路也不复杂,以空间换时间。
复杂版代码如下:
class Solution {
public:
    int GetUglyNumber_Solution(int index) {
		if ( index <= 0 ) return 0 ;
        
        int* arr = new int[index] ;
        arr[0] = 1 ;
        int* multi2 = arr ;
        int* multi3 = arr ;
        int* multi5 = arr ;
        int nextIndex = 1 ;
        
        while ( nextIndex < index ) {
            int min = MIN( (*multi2) * 2, (*multi3) * 3, (*multi5) * 5 ) ;
            arr[nextIndex] = min ;
            
            while ( *multi2 * 2 <= min ) multi2++ ;
            while ( *multi3 * 3 <= min ) multi3++ ;
            while ( *multi5 * 5 <= min ) multi5++ ;
            
            nextIndex++ ;
        }
        
        int result = arr[nextIndex - 1] ;
        if ( arr != NULL ) delete[] arr ;
        
        return result ;
    }
    
    int MIN( int n1, int n2, int n3 ) {
        int tmp = n1 < n2 ? n1 : n2 ;
        return tmp < n3 ? tmp : n3 ;
    }
};
有两个地方要注意:
1.
int result = arr[nextIndex - 1] ;
写成
int result = arr[nextIndex - 1] ;
是错误的, nextIndex要回退一个步长。
2.函数结束前delete指针时我一开始这样写的:
        if ( arr != NULL ) delete[] arr ;
        if ( multi2 != NULL ) delete multi2 ;
        if ( multi3 != NULL ) delete multi3 ;
        if ( multi5 != NULL ) delete multi5 ;
这四个指针指向的同一个内存空间
if ( arr != NULL ) delete[] arr ;
已经归还了内存,但是我还delete了multi2、multi3、multi5,导致同一块内存释放了三次,这无法通过编译。

第二次做:
依然采用第一次做的方法
class Solution {
public:
    int GetUglyNumber_Solution(int index) {
    	if ( index <= 0 ) return 0 ;
        
        int* p = new int[index] ;
        int* p2 = p ;
        int* p3 = p ;
        int* p5 = p ;
        
        p[0] = 1 ;
        int cur = 1 ;
        int minVal = 1 ;
        while ( cur < index ) {
            minVal = min( *p2 * 2, *p3 * 3, *p5 * 5 ) ;
            p[cur] = minVal ;
            
            while ( *p2 * 2 <= p[cur] ) 
                ++ p2 ;
            while ( *p3 * 3 <= p[cur] ) 
                ++ p3 ;
            while ( *p5 * 5 <= p[cur] ) 
                ++ p5 ;
            
            ++ cur ;
        }
        
        int retVal = p[cur - 1] ;
        delete[] p ;
        return retVal ;
    }
    
    int min( int i1, int i2, int i3 ) {
        int min1 = i1 < i2 ? i1 : i2 ;
        return min1 < i3 ? min1 : i3 ;
    }
};

第三次做:
class Solution {
public:
    int GetUglyNumber_Solution(int index) {
    	if ( index <= 0 ) return 0 ;
        
        int* p = new int[index] ;
        p[0] = 1 ;
        int* p2 = &p[0] ;
        int* p3 = p ;
        int* p5 = p ;
        
        int cur = 1 ;
        while ( cur < index ) {
            int tmp = min( *p2 * 2, *p3 * 3, *p5 * 5 ) ;
            p[cur] = tmp ;
            
            while ( *p2 * 2 <= tmp ) ++p2 ;
            while ( *p3 * 3 <= tmp ) ++p3 ;
            while ( *p5 * 5 <= tmp ) ++p5 ;
            
            ++ cur ;
        }
        
        int retVal = p[cur - 1] ;
        delete[] p ;
        return retVal ;
    }
    
    int min( int n1, int n2, int n3 ) {
        int tmp = n1 < n2 ? n1 : n2 ;
        return tmp < n3 ? tmp : n3 ;
    }
};


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值