第33题——丑数

157 阅读2分钟

题目:

把只包含质因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含质因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。

思路:

摘自牛客评论——一个丑数的因子只有2,3,5,那么丑数p=2^x*3^y*5^z,即一个丑数一定是由另一个丑数乘以2或者乘以3或者乘以5而得。那么维护三个队列,分别是乘以2,乘以3和乘以5的队列,1乘以2,3,5得到丑数2,3,5,2,3,5再乘以2,3,5又得到4,6,10,6,9,15,10,15,25,这并不是有序的,因此,需要这样做:

丑数数组中:1

乘以2队列:|2
乘以3队列:|3
乘以5队列:|5

"|"代表队首位置,每次比较队首的元素,小的出队加入丑数数组中

丑数数组中:1,2

乘以2队列:2,|4
乘以3队列:|3,6
乘以5队列:|5,10

丑数数组中:1,2,3

乘以2队列:2,|4,6
乘以3队列:3,|6,9
乘以5队列:|5,10,15

丑数数组中:1,2,3,4

乘以2队列:2,4,|6,10
乘以3队列:3,|6,9,15
乘以5队列:|5,|10,15,25

丑数数组中:1,2,3,4,5,6

乘以2队列:2,4,6,|10,12
乘以3队列:3,6,|9,15,18
乘以5队列:5,|10,15,25,30

Java

package nowcoder;

import java.util.ArrayList;

public class S33_UglyNumber {
    public int uglyNumber(int index){
        if (index < 7) return index;
        ArrayList<Integer> arr = new ArrayList<Integer>();
        arr.add(1); //将1加入丑数数组中
        int p2 = 0, p3 = 0, p5 = 0;
        while (arr.size() < index) {
            int v2 = arr.get(p2) * 2;
            int v3 = arr.get(p3) * 3;
            int v5 = arr.get(p5) * 5;
            int min = Math.min(v2, Math.min(v3, v5));
            arr.add(min);
            if (v2 == min) p2++;
            if (v3 == min) p3++;
            if (v5 == min) p5++;
        }
        return arr.get(arr.size()-1);
    }
    public static void main(String[] args){
        S33_UglyNumber s33 = new S33_UglyNumber();
        System.out.println(s33.uglyNumber(100));
    }
}

Python

class UglyNumber:
    def UglyNumber(self, index):
        arr = [1]
        if index < 7:
            return index
        p2, p3, p5 = 0, 0, 0
        while len(arr) < index:
            v2 = arr[p2] * 2
            v3 = arr[p3] * 3
            v5 = arr[p5] * 5
            mini = min(v2, v3, v5)
            arr.append(mini)
            if v2 == mini: p2 += 1
            if v3 == mini: p3 += 1
            if v5 == mini: p5 += 1
        return arr[-1]
if __name__ == '__main__':
    test = UglyNumber()
    print(test.UglyNumber(100))

结果

1536