【题49】 丑数

【题目】
把只包含质因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含质因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。
【思路】
方法一
一个数m是另一个数n的因子,是指m能被m整除,即n %m = 0。
丑数只能被2,3,5整除.即
如果一个数能被2整除,连续除以2;
如果一个数能被3整除,连续除以3;
如果一个数能被5整除,连续除以5.
如果最后得到的是1,那么就是丑数,否则不是。

方法二
一个丑数的因子只有2,3,5,
定义丑数p = 2 ^ x * 3 ^ y * 5 ^ z,
即一个丑数一定由另一个丑数乘以2或者乘以3或者乘以5得到。
从1开始乘以2,3,5,就得到2,3,5三个丑数,在从这三个丑数出发乘以2,3,5就得到4,6,10,6,9,15,10,15,25九个丑数,这种方法会得到重复的丑数,题目要求第N个丑数,这样的方法得到的丑数也是无序的。所以可以维护三个队列:
(1)丑数数组: 1
乘以2的队列:2
乘以3的队列:3
乘以5的队列:5
选择三个队列头最小的数2加入丑数数组,同时将该最小的数乘以2,3,5放入三个队列;
(2)丑数数组:1,2
乘以2的队列:4
乘以3的队列:3,6
乘以5的队列:5,10
选择三个队列头最小的数3加入丑数数组,同时将该最小的数乘以2,3,5放入三个队列;
(3)丑数数组:1,2,3
乘以2的队列:4,6
乘以3的队列:6,9
乘以5的队列:5,10,15
选择三个队列头里最小的数4加入丑数数组,同时将该最小的数乘以2,3,5放入三个队列;
(4)丑数数组:1,2,3,4
乘以2的队列:6,8
乘以3的队列:6,9,12
乘以5的队列:5,10,15,20
选择三个队列头里最小的数5加入丑数数组,同时将该最小的数乘以2,3,5放入三个队列;
(5)丑数数组:1,2,3,4,5
乘以2的队列:6,8,10,
乘以3的队列:6,9,12,15
乘以5的队列:10,15,20,25
选择三个队列头里最小的数6加入丑数数组,但我们发现,有两个队列头都为6,所以我们弹出两个队列头,同时将12,18,30放入三个队列;
……………………
在实现时,只要找到乘以2,乘以3,乘以5的最后一个数即可(因为有序),在比较这三个数的大小,选择最小的加入到数组。

【实现】

public class Chou {
	public static int GetUglyNumber_Solution(int index) {
		if (index <= 0)
			return 0;
		int[] result = new int[index];
		result[0] = 1;//把1当作第一个丑数
		int M2 = 0;// 数组最后一个2的倍数所在位置
		int M3 = 0;// 数组最后一个3的倍数所在位置
		int M5 = 0;// 数组最后一个5的倍数所在位置
		for (int i = 1; i < index; i++) {
			// 每一个丑数都是前面丑数乘以2,3或者5得到的
			int min = min(result[M2] * 2, result[M3] * 3, result[M5] * 5);//调用min函数
			result[i] = min;//找到三个数中最小值添加到result数组
			if (result[M2] * 2 <= min)
				M2++;
			if (result[M3] * 3 <= min)
				M3++;
			if (result[M5] * 5 <= min)
				M5++;
 
		}
 
		return result[index - 1];
	}
	public static int min(int a, int b, int c) {//找到三个数的最小值
		int min = (a < b) ? a : b;
		return (min < c) ? min : c;
	}
}

【例】
在这里插入图片描述

参考:
1.《剑指offer》
2.https://blog.csdn.net/pomay/article/details/74457006
3.https://www.nowcoder.com/profile/835689/codeBookDetail?submissionId=1522621
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_39795049/article/details/88614437
今日推荐