剑指offer:丑数

题目描述

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

直接去使用遍历循环是不可以的,其时间太久,通过观察一个丑数必定是由另外一个丑数得来。

使用一个数组,里面放都是丑数,数组后面的数必定是前面的数乘以2,3,5得来的,关键就是确保数组里的丑数是有序的,

以下是构建有序丑数序列的算法

   我们把现有的最大丑数记做M。现在我们来生成下一个丑数,该丑数肯定是前面某一个丑数乘以23或者5的结果。

   我们考虑记录2、3、5的对所求数组位置的元素的乘积,把已有的每个丑数乘以2、3、5由于我们是按照顺序生成的,小于或者等于M肯定已经在数组中了,我们不需再次考虑;我们还会得到若干个大于M的结果,但我们只需要第一个大于M的结果,因为我们希望丑数是按从小到大顺序生成的,其他更大的结果我们以后再说。我们把得到的第一个乘以2后大于M的结果,记为M2

   同样我们把已有的每一个丑数乘以35,能得到第一个大于M的结果M3M5那么下一个丑数应该是M2M3M5三个数的最小者。

细节处理: 1、注意从一开始,对数组下标和具体数的对应关系;

               2、注意对丑数进行确定后,像6=3*2,6=2*3这种的处理,这里需要同时对2和3的要乘的数组的元素后移;

               3、但是需要在起初初始化一个很大的数组,空间换取了时间的效率;

扫描二维码关注公众号,回复: 1692629 查看本文章
import java.util.*;
public class Solution {
    public int GetUglyNumber_Solution(int index) {
        if(index<=0)
            return 0;
        int[] result = new int[index];
        int count = 0;
        int i2 = 0;
        int i3 = 0;
        int i5 = 0;
        result[0] = 1;
        int tmp = 0;
        while (count < index-1) {
            tmp = min(result[i2] * 2, min(result[i3] * 3, result[i5] * 5));
            if(tmp==result[i2] * 2) i2++;//三条if防止值是一样的,不要改成else的
            if(tmp==result[i3] * 3) i3++;//这里的必须有这个判断,否则重复记录
            if(tmp==result[i5] * 5) i5++;
            result[++count]=tmp;
        }
        return result[index - 1];
    }
 
    private int min(int a, int b) {
        return (a > b) ? b : a;
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_30363263/article/details/80739168