Swift學習——尋找醜數

參考自:http://www.cnblogs.com/python27/archive/2011/11/24/2261550.html

題目:我們把只包含因子2、3和5的數稱作醜數(Ugly Number)。例如6、8都是醜數,但14不是,因爲它包含因子7。習慣上我們把1當做是第一個醜數。求按從小到大的順序的第1500個醜數。

  分析:尋找一個數是不是滿足某種數(質數,水仙數)等,最簡單的方法就是遍歷,對於任意一個醜數必定可以寫成2^m*3^n*5^p,因而對於一個醜數,只含有2,3,5因子,也就意味着該數number%2==0;number%3==0;number%5==0,如果一個數能被2整除,我們就連續除以2;能被3整除,我們就連續除以3;能被5整除,我們就連續除以5;如果最後得到1,則該數是素數,否則是醜數。

  代碼如下:

func isUglyNumber(number:Int)->Bool
{
    var number1 = number
    while number1 % 2 == 0
    {
        number1 /= 2
    }
    while number1 % 3 == 0
    {
        number1 /= 3
    }
    while number1 % 5 == 0
    {
        number1 /= 5
    }
    if number1 == 1
    {
        return true
    }
    else{
        return false
    }
}


func getUglyNumber1(index:Int)->Int{
    if index <= 0{
        return 0
    }
    var number:Int = 0
    var count:Int = 0
    while(count < index)
    {
        ++number
        if isUglyNumber(number){
            ++count
        }
    }
    return number
}

上面計算中主要的不足在於,逐一遍歷,這樣對於不是醜數的數的判斷會造成大量的時間浪費,如果能夠根據已經計算好的醜數,計算出下一個醜數就可以避免這種情況,實現從醜數到醜數的高效算法,根據定義可知,後面的醜數肯定是前面已知醜數乘以2,3,5得到的。

  我們假設一個數組中已經有若干醜數,並且這些醜數是按順序排列的,我們把現有的最大丑數記爲max,則下一個醜數肯定是前面醜數乘以2,3,5得到的。不妨考慮乘以2得到的情況,我們把數組中的每一個數都乘以2,由於原數組是有序的,因爲乘以2後也是有序遞增的,這樣必然存在一個數M2,它前面的每一個數都是小於等於max,而包括M2在內的後面的數都是大於max的,因爲我們還是要保持遞增順序,所以我們取第一個大於max的數M2。同理對於乘以3的情況,可以取第一個大於max的數M3,對於乘以5的情況,可以取第一個大於max的數M5。

  最終下一個醜數取:min{M2,M3,M5}即可
  (相當於將之前得到的醜數放到一個數組array裏,然後分別將數組array裏的醜數乘以2,將其與數組array的最後一個醜數b相比,一旦大於b,就稱其爲上述中的M2,同理可得M3,M5)
  代碼如下:
  

func getUglyNumber2(index:Int)->Int{
    var uglyNum:Int = 1
    if index <= 0{
        return 0
    }
    var uglyArray:Array<Int> = [1]
    var m2Array:Array<Int> = Array()
    var m3Array:Array<Int> = Array()
    var m5Array:Array<Int> = Array()
    while uglyArray.count < index{
        var m2:Int = 0
        var m3:Int = 0
        var m5:Int = 0
        m2Array = uglyArray
        m3Array = uglyArray
        m5Array = uglyArray
        for (index,value) in enumerate(m2Array){
            m2Array[index] = value*2
            if m2Array[index] > uglyArray.last{
                m2 = m2Array[index]
                break
            }
        }
        for (index,value) in enumerate(m3Array){
            m3Array[index] = value*3
            if m3Array[index] > uglyArray.last{
                m3 = m3Array[index]
                break
            }
        }
        for (index,value) in enumerate(m5Array){
            m5Array[index] = value*5
            if m5Array[index] > uglyArray.last{
                m5 = m5Array[index]
                break
            }
        }

        uglyNum = min(m2, m3, m5)
        uglyArray.append(uglyNum)
    }
    return uglyNum
}

在此感謝http://www.cnblogs.com/python27/的每日一算法的分享

發佈了34 篇原創文章 · 獲贊 3 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章