剑指offer|丑数

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

时间限制:1秒 空间限制:32768K 热度指数:265042
本题知识点: 数组

【思路分析】

法一:暴力求解法

  1. 了解并书写判断一个数是不是丑数的规则;
  2. 从1开始,依次判断是否为丑数,是则丑数计数器++,直到计数器的值为要求的值。

此种解法需要对从1开始的每一个数进行验证,做了些无用功。

法二: 利用丑数的生成规则

依据丑数的定义,我们知道 每一个丑数可以由 排在其前面的丑数乘以2、乘以3 或 乘以5构成 。故我们可以依次按照递增顺序生成丑数。下面就需要考虑如何递增生成丑数:

  1. 1是第一个丑数;
  2. 第二个丑数为 min(1 * 2, 1 * 3, 1 * 5) = 2;
  3. 第三个丑数为 min(1 * 2, 1 * 3, 1 * 5, 2 * 2, 2 * 3, 2 * 5) = 3;
  4. 第四个丑数为 min(1 * 2, 1 * 3, 1 * 5, 2 * 2, 2 * 3, 2 * 5, 3 * 2, 3 * 3, 3 * 5) = 5;
  5. 第三个丑数为 min(1 * 2, 1 *3 , 1 * 5, 2 * 2, 2 * 3, 2 * 5, 3 * 2, 3 *3 , 3 * 5, 5 * 2, 5 * 3, 5 * 5) = 4;

经过分析:

  • 在求第三个丑数时 1 * 2 这一项是无用的(已经用过了),所以在每找到一个丑数时,其对应的指针应该++;
  • 在求第三个丑数时, 2 * 3, 2 * 5 这两项一定大于 1 * 3, 1 * 5这两项,故 2 * 3, 2 * 5 可省略。

故,以上可简化为:

  1. 1是第一个丑数;
  2. 第二个丑数为 min(1 * 2, 1 * 3, 1 * 5) = 2;
  3. 第三个丑数为 min(2 * 2, 1 * 3, 1 * 5) = 3;
  4. 第四个丑数为 min(2 * 2, 2 * 3, 1 * 5) = 5;
  5. 第三个丑数为 min(2 * 2, 2 * 3, 2 * 5) = 4;

代码如下:

import java.util.ArrayList;
import java.lang.Math;

public class Solution {
    // 30ms 9324K
    public int GetUglyNumber_Solution(int index) {
        // 1 2 3 4 5 6
        if(index < 7)
            return index;
        
        // list用于按照递增顺序存储丑数
        ArrayList<Integer> list = new ArrayList<>();
        list.add(1);
        
        int v2 = 0,v3 = 0,v5 = 0;
        
        while(list.size() < index){
            int num2 = list.get(v2) * 2;
            int num3 = list.get(v3) * 3;
            int num5 = list.get(v5) * 5;
            
            int min =  Math.min(num2, Math.min(num3, num5));
            list.add(min);
            
            if(min == num2)
                v2++;
            if(min == num3)
                v3++;
            if(min == num5)
                v5++;
            
        }        
        return list.get(list.size()-1);
    }
}

你可能感兴趣的:(刷题)