您的位置:首页 > 其它

39.Ugly Number II(动态规划)

2015-10-23 12:27 197 查看
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
;
}


总结:清晰的思路,即使遇到看上去不会的题目,也不能太着急。慢慢来分析,总会找得到答案,加油@@@
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: