39.Ugly Number II(动态规划)

Write a program to find the n-th ugly number.

Ugly numbers are positive numbers whose prime factors only include 2, 3, 5. For example, 1, 2, 3, 4, 5, 6, 8, 9, 10, 12 is the sequence of the first 10 ugly numbers.

Note that 1 is typically treated as an ugly number.

分析:找出第n个丑数。

方法一:

用三个l2,l3,l5的头节点分别表示该乘2,3,5的丑数。然后比较这三个值的大小,取最小的那个,然后把新的丑数分别加入到三个链表的尾部。最后返回尾节点的值。

即知道了第n-1个丑数,则第n个丑数是min(l2*2,l3*3,l5*5)中的那个。

int getMin(int a,int b,int c){
		if(a<b){
			if(a<c){
				return a;
			}else{
				return c;
			}
		}else{
			if(b<c){
				return b;
			}else{
				return c;
			}
		}
	}
	
	 /*找出第n个丑数*/
	 public int nthUglyNumber(int n) {
		 if(n == 1){
			 return 1;
		 }
		 ListNode l2 = new ListNode(1);//用三个节点保存一样的丑数序列,知道了第(n-1)个丑数,则第n个则是l2*2,l3*3,l5*5中最小的那个,然后该链表指向下一个。并且把新得到的那个加入到三个链表的最后
		 ListNode l3 = new ListNode(1);
		 ListNode l5 = new ListNode(1);
		
		 ListNode t2 = l2;//尾节点
		 ListNode t3 = l3;
		 ListNode t5 = l5;
		 
		 for(int i = 2 ; i<=n; i++){
			 
			 int a = l2.val * 2;
			 int b = l3.val * 3;
			 int c = l5.val * 5;
			 int min = getMin(a,b,c);
			 
			 t2.next = new ListNode(min);
			 t2 = t2.next;
			 t3.next = new ListNode(min);
			 t3 = t3.next;
			 t5.next = new ListNode(min);
			 t5 = t5.next;
			 
			 if(a == min){
				 l2 = l2.next;
			 }
			 if(b == min){
				 l3 = l3.next;
			 }
			 if(c == min){
				 l5 = l5.next;
			 }
			 
		 }
		 System.out.println(t2.val );
		 return t2.val;
	    }

方法二:可以对方法一进行简单的改进。把维护三个链表修改为维护一个链表,只不过是让l2,l3,l5分别表示对应下一个该乘2,3,5的节点。

 public int nthUglyNumber2(int n) {
		 if(n == 1){
			 return 1;
		 }
		//把方法一中的三个链表变成一个链表。
		 ListNode l2 = new ListNode(1);//表示下一个该比较的乘2节点
		 ListNode l3 = l2;//表示下一个该比较的乘3节点
		 ListNode l5 = l3;//表示下一个该比较的乘5节点
		
		 ListNode t2 = l2;//尾节点
		 
		 for(int i = 2 ; i<=n; i++){
			 
			 int a = l2.val * 2;
			 int b = l3.val * 3;
			 int c = l5.val * 5;
			 int min = getMin(a,b,c);
			 
			 t2.next = new ListNode(min);
			 t2 = t2.next;
			 
			 if(a == min){
				 l2 = l2.next;
			 }
			 if(b == min){
				 l3 = l3.next;
			 }
			 if(c == min){
				 l5 = l5.next;
			 }
			 
		 }
		 System.out.println(t2.val );
		 return t2.val;
	    }
	

方法三:用数组代替上述链表方法存储丑数。

后一个丑数肯定是在之前的丑数基础上乘以2或3或5得到的。

因此可以用数组保存已经求得的丑数,l2保存下一个该比较的乘2的结点的下标,l3保存下一个该比较的乘3的结点的下标,l5保存下一个该比较的乘5的结点的下标。

 public int nthUglyNumber3(int n) {//提交通过
		 if(n == 1){
			 return 1;
		 }
		 
		 int[] nums = new int[n+1];//用数组存之前的丑数,其中nums[i]表示第i个丑数
		 nums[1]=1;
		 
		 int l2 = 1;//表示下一个该比较的乘2节点
		 int l3 = 1;//表示下一个该比较的乘3节点
		 int l5 = 1;//表示下一个该比较的乘5节点
		 
		 for(int i = 2 ; i<=n; i++){
			 
			 int a = nums[l2] * 2;
			 int b = nums[l3] * 3;
			 int c = nums[l5] * 5;
			 int min = getMin(a,b,c);

			 nums[i]=min;
			 
			 if(a == min){
				 l2++;
			 }
			 if(b == min){
				 l3++;
			 }
			 if(c == min){
				 l5++;
			 }
			 
		 }
		 return nums[n];
	    }


总结:清晰的思路,即使遇到看上去不会的题目,也不能太着急。慢慢来分析,总会找得到答案,加油@@@



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值