剑指offer31--丑数

题目:我们把只包含因子2、3 和5 的数称作丑数(Ugly Number)。求从小到大的顺序的第1500个丑数。

例如:6、8 都是丑数,但14 不是,它包含因子7。习惯上我们把1 当做第一个丑数。

编程思路:

(1)丑数都是前面的丑数乘以2、3、5得到的。

(2)然后问题点变成了我们怎么把前面的丑数排好序,将所有数都乘以2,找到刚好大于大于最大值M的T2,这样我们也能找到刚刚好大于最大丑数M的T3和T5,将3个数相比较,得到3个数中最小的那个,并将此数的值赋给丑数数组的最大元素。

(3)循环多次这样的过程,得到我们所需要的第n个丑数。

(4)其实第二步中,我们不需要把所有的数都乘以2/3/5,因为flag2、flag3、flag5都相当于一个指针,他们是一直向前移动的,没有必要向后移动。

package 剑指offer;
/*题目:我们把只包含因子2、3 和5 的数称作丑数(Ugly Number)。求从小到大的顺序的第1500个丑数。*/
public class Test34 {
	// 其中index是要发现第多少个丑数
	public static int findUglyNum(int index){
		if(index < 0){
			System.out.print("Number Error");
		}
		
		int [] uglyNum = new int[index];
		uglyNum[0] = 1;
		int nextIndex = 1;
		
		// 分别定义2/3/5的下标标志
		int flag2 = 0;
		int flag3 = 0;
		int flag5 = 0;
		
		while(nextIndex < index){
			// 首先要对uglyNum[nextIndex]进行初始化,那么首先要有一个他下面才可以比较
			// 其实每比较一轮,丑数的集合中就增加一个数,三个flag也是不断先前赶的
			int minNum = findMinNumber(uglyNum[flag2] * 2, uglyNum[flag3] * 3, uglyNum[flag5] * 5);
			uglyNum[nextIndex] = minNum;
			
			while(uglyNum[flag2] * 2 <= uglyNum[nextIndex]){
				flag2++;
			}
			while(uglyNum[flag3] * 3 <= uglyNum[nextIndex]){
				flag3++;
			}
			while(uglyNum[flag5] * 5 <= uglyNum[nextIndex]){
				flag5++;
			}
			nextIndex++;
		}
		
		return uglyNum[nextIndex - 1];
	}
	
	public static int findMinNum(int a, int b, int c){
		if(a <= b && a <= c){
			return a;
		}else if(b <= a && b <= c){
			return b;
		}else if(c <= a && c <= b){
			return c;
		}
		return 0;
	}
	
	// 上面比较大小应该使用简便方法,这样太麻烦了
	public static int findMinNumber(int a, int b, int c){
		int min = a < b?a:b;
		return min < c?min:c;
	}
	
	public static void main(String args[]){
		 	System.out.println(findUglyNum(7)); // 8
	        System.out.println(findUglyNum(8)); // 9
	        System.out.println(findUglyNum(9)); // 10
	        System.out.println(findUglyNum(10)); // 12
	        System.out.println(findUglyNum(11)); // 15
	        System.out.println(findUglyNum(1500)); // 859963392
	}
}

丑数其实并不丑

你可能感兴趣的:(剑指offer31--丑数)