39.Ugly Number II(动态规划)

本文详细介绍了三种方法来找出第n个丑数,包括使用链表的方法、改进后的链表方法以及数组存储法。每种方法都旨在通过清晰的思路解决这个问题,并提供代码实现以供参考。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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];
	    }


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



### 关于LeetCode Python 150道题目实践 在准备技术面试的过程中,解决编程问题是提升技能的重要方式之一。对于Python开发者而言,在LeetCode平台上完成一系列经典问题可以帮助巩固基础知识并提高解决问题的能力。以下是关于如何高效利用LeetCode平台以及推荐的150道Python相关题目列表。 #### 高效使用LeetCode的方法 尽管提到LeetCode存在一些局限性[^1],比如缺乏对代码可读性和变量命名的要求,但它仍然是学习算法和数据结构的有效工具。为了弥补这些不足之处,可以采取以下策略: - **注重代码质量**:即使LeetCode不强制执行良好的编码习惯,也应主动优化自己的代码风格,包括清晰的变量名、合理的函数拆分等。 - **深入分析解法**:每次提交解答之后,尝试思考是否有更优的时间复杂度或者空间复杂度改进方案,并研究其他用户的高赞答案以获取灵感。 - **模拟真实场景**:通过自行设计扩展需求来增强原题目的挑战程度,从而锻炼应对实际工作中可能出现的变化情况。 #### 推荐的150道Python题目分类 下面按照难度等级划分了一些适合初学者到高级程序员练习的经典习题: ##### 易 (Easy Level) ```plaintext 1. Two Sum 2. Reverse Integer ... (共约40道简单级别题目省略显示) ``` ##### 中等 (Medium Level) ```plaintext 41. First Missing Positive 42. Trapping Rain Water ... (大约70道中等等级题目同样仅列举部分名称如下:) 88. Merge Sorted Array 94. Binary Tree Inorder Traversal ... ``` ##### 困难 (Hard Level) ```plaintext 114. Flatten Binary Tree to Linked List 124. Binary Tree Maximum Path Sum ... (最后大概有40道较难题目举例说明其中几个:) 239. Sliding Window Maximum 264. Ugly Number II ... ``` 由于篇幅原因无法逐一列出全部具体编号与描述,请访问官方网站筛选标签为`Python`的相关条目即可找到完整的清单链接地址[^2]. #### 示例代码片段展示 这里给出一道常见入门级别的例子——两数之和(Two Sum),附带简洁易懂实现版本供参考: ```python def twoSum(nums, target): num_to_index = {} for i, num in enumerate(nums): complement = target - num if complement in num_to_index: return [num_to_index[complement], i] num_to_index[num] = i raise ValueError("No solution found.") ``` 此方法采用哈希表记录已遍历过的数值及其索引位置关系,能够显著降低时间消耗至O(n)水平[^3]. ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值