剑指offer(三十三)——丑数

剑指offer(三十三)——丑数

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

题解
理解题意很重要,咋一看会感觉丑数很复杂,但实际上你把它列出来就会发现,丑数定义是比较简单的。1、2、3、4、5、6、8、9、10、12、15、18、20、25……仔细琢磨就会发现

  • 2=1*2
  • 3=1*3
  • 5=1*5
  • 4=2*2
  • 6=2*3
  • 10=2*5
  • 6=3*2
  • 9=3*3
  • 15=3*5
  • ……
    可以看出来丑数都是由丑数相乘得来的。在知道了定义之后我们能做什么?这里有一位大佬的解释就很清楚。

链接:https://www.nowcoder.com/questionTerminal/6aa9e04fc3794f68acf8778237ba065b?f=discussion
来源:牛客网

维护三个队列:
(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

这样看思路是不是比较明朗了?但是3个队列就显得比较麻烦,所以我们用3个指针也可以达到相同的效果。
在这里插入图片描述

  • p1、p2、p3三个指针用来取代队列的作用,由于默认1是丑数数组的第一位,所以先让指针指向丑数数组list[0],分别乘上2、3、5,结果中最小的便是下一位丑数,这里是2。
    在这里插入图片描述
  • 将2存入list中,并移动指针p1,然后重复乘上2、3、5,结果最小即是下一位丑数。在这里插入图片描述在这里插入图片描述
  • 这样便可以求出题目所要求的数了。
public int GetUglyNumber_Solution(int index) {
		if (index < 7) {
			return index;
		}
		ArrayList<Integer> list = new ArrayList<>();
		list.add(1);
		int i, p1 = 0, p2 = 0, p3 = 0;
		for(i = 1; i < index; i++) {
			int mulTwo = list.get(p1) * 2;
			int mulThr = list.get(p2) * 3;
			int mulFiv = list.get(p3) * 5;
			int minNum = Math.min(mulTwo, Math.min(mulThr, mulFiv)); 
			list.add(minNum);
			if (minNum == mulTwo) {
				p1++;
			}
			if (minNum == mulThr) {
				p2++;
			}
			if (minNum == mulFiv) {
				p3++;
			}
		}
        return list.get(index - 1);
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章