• 剑指offer三十三--第n个丑数


    前言:本文只提供了解题的思路,代码只有想法二的,但想法二不是最优解。如果你想找一个最好答案,可能本文不合适。如果你想一步一步接近最优答案的话,可以耐心看完。

    题目描述

    把只包含质因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含质因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。
    前20个丑数为:1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, 18, 20, 24, 25, 27, 30, 32, 36。

    解题思路

    想法一

    写一个判断是否为丑数的函数,这个函数代码依次将2,3,5除尽。若最后为1则是丑数
    从1往后找,找满n个丑数为止
    代码如下

    bool PanDuan(int val) {
    		if (val == 1)
    			return true;
    
    		// 把2的因子除尽
    		while (val % 2 == 0) {
    			val /= 2;
    		}
    		// 把3的因子
    		while (val % 3 == 0) {
    			val /= 3;
    		}
    		// 5
    		while (val % 5 == 0) {
    			val /= 5;
    		}
    
    		if (val == 1)
    			return true;
    		else
    			return false;
    	}
    

      

    想法二

    第i个丑数由前面i-1个数中的某个数 乘以 2 3 5得到,我们找的乘后的数要大于第i-1个丑数,且尽可能的小
    那求第i个丑数,将前面的i-1个数依次遍历,遍历一个数时 让其 乘以2 3 5;
    结果 要大于第i-1个整数,且尽可能的小。
    由前面的东西给推出后面,是一种动态规划的写法,但存在重复计算。
    代码见最后;

    想法三

    方法2存在重复计算 算3要遍历1、2所有 算4 还是要遍历1、2.可以想办法把计算结果保存起来能起来。具体来说 丑数数组A 存放前i-1个丑数数组(没有钱i-1个丑数) 乘以2 3 5后容器B
    从B中取最小的数x加入到A中,然后取出的数x乘以2 3 5放入到容器B中
    如此反复直到丑数数组A数量达到n
    对于容器B 有如下两种方式

    容器:一个set

    保存方式由两种建一个set 存由已知丑数得到的结果,然后取set最小的值为下一个丑数 乘以2 3 5得到三个数加入set中
    缺点是每次加入三个数后都要重新排序,因为顺序不固定

    容器:三个队列

    保存方式2创建3个队列 乘以2 3 5所得数列,这样避免了重新排序,具体见实例
    丑数数组;
    (1)丑数数组A1
    乘以2队列|2
    乘以3队列|3
    乘以5队列|5
    (2)丑数数组1 2
    乘以2 |4
    乘以3|3 6
    乘以5|5 10
    (3)丑数数组1 2 3
    乘以2| 4 6
    乘以3 |6 9
    乘以5|5 10 15

    代码C++

    想法二

    class Solution {
    public:	
        int GetUglyNumber_Solution(int index) {
    		if (index == 1 || index == 2 || index == 3)
    			return index;
    		vector<int> uglys;
    		uglys.push_back(1);
    		
    		for (int i = 1; i < index; i++) {//依次计算出第i个丑数,i是下标
    			int min = INT32_MAX; //记录由前面的ugly获取第i个丑数的最小值
    			for (int j = i - 1; j >= 0; j--) {
    				if (uglys[j] * 2 > uglys[i - 1] && uglys[j] * 2 < min) {
    					min = uglys[j] * 2;
    				}
    				else if (uglys[j] * 3 > uglys[i - 1] && uglys[j] * 3 < min) {
    					min = uglys[j] * 3;
    				}
    				else if(uglys[j] * 5 > uglys[i - 1] && uglys[j] * 5 < min) {
    					min = uglys[j] * 5;
    				}			
    			}
    			uglys.push_back(min);
    		}
    		return uglys[index - 1];
    	}
    };
    

      

  • 相关阅读:
    五步搞定Android开发环境部署!
    WebBrowser JS回调delphi的方法 (简单通用)
    Delphi根据方法名调用方法
    Delphi TstringList Stringlist的特殊用法
    delphi 获取webbrowser的cookies给Idhttp用
    HttpHelper类登录淘宝联盟并下载淘宝客订单xls
    我的常用笔记(GetAndroid,ADBDemo,GetSJ,GetTB)
    P1025 数的划分
    P1969 积木大赛
    P2038 无线网络发射器选址
  • 原文地址:https://www.cnblogs.com/linxuesong/p/12214629.html
Copyright © 2020-2023  润新知