首页 > 试题广场 >

丑数

[编程题]丑数
  • 热度指数:589174 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
把只包含质因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含质因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第 n个丑数。

数据范围:
要求:空间复杂度 , 时间复杂度
示例1

输入

7

输出

8
推荐
class Solution {
public://别人的代码就是精简,惭愧啊,继续学习。
    int GetUglyNumber_Solution(int index) {
		if (index < 7)return index;
		vector<int> res(index);
		res[0] = 1;
		int t2 = 0, t3 = 0, t5 = 0, i;
		for (i = 1; i < index; ++i)
		{
			res[i] = min(res[t2] * 2, min(res[t3] * 3, res[t5] * 5));
			if (res[i] == res[t2] * 2)t2++;
			if (res[i] == res[t3] * 3)t3++;
			if (res[i] == res[t5] * 5)t5++;
		}
		return res[index - 1];
    }
};

编辑于 2019-01-10 19:24:15 回复(145)
function GetUglyNumber_Solution(index)
{
    // write code here
    if(index < 7) return index
    let p2 = 0, p3 = 0, p5 = 0  //计算下一个丑数的位置
    let res = []  //存放排好序的丑数
    res[0] = 1
    for(let i =1; i < index; i++){
        res[i] = Math.min(res[p2]*2, Math.min(res[p3]*3,res[p5]*5)) //取最小值
        //移动相应的位置
        if(res[i] === res[p2]*2) p2++;
        if(res[i] === res[p3]*3) p3++;
        if(res[i] === res[p5]*5) p5++;
    }
    //返回最后一个
    return res[index-1];
}

发表于 2021-09-02 20:41:15 回复(0)
这个方法可能会比较好理解,但是占用内存挺大的,记录一下。
定义两个数组,一个用作存放丑数结果,另一个用作比较大小。
对前一个丑数分别*2,*3,*5,放进用作比较的数组,然后取出最小数放进保存结果的数组。
function GetUglyNumber_Solution(index)
{
    // write code here
    let arr=[];             //用作比较的数组
	let res=[1];            //保存结果的数组
    if(index==0){
	return 0};
	for(let i=0;i<index;i++){
		arr.push(res[i]*2,res[i]*3,res[i]*5);
		arr.sort((a,b)=>{
			return a-b;
		})
		arr=Array.from(new Set(arr));
		res.push(arr[0]);
		arr.splice(0,1);
	}
	return res[index-1]
}


编辑于 2021-06-08 18:35:43 回复(0)
function GetUglyNumber_Solution(index)
{
    // write code here
    if(index == 0){
        return 0;
    }
    var dp = [];
    var i2 = 0, i3 = 0, i5 = 0;
    dp[0] = 1;
    for(var i = 1;i < index;i++){
        dp[i] = Math.min(dp[i2] * 2, dp[i3] * 3, dp[i5] * 5);
        if(dp[i] == dp[i2] * 2){
            i2++;
        }
        if(dp[i] == dp[i3] * 3){
            i3++;
        }
        if(dp[i] == dp[i5] * 5){
            i5++;
        }
    }
    return dp[index - 1];
}
动态规划思想
发表于 2021-03-20 13:06:20 回复(0)
1.如果被判断的数是1、2、3、5其中的一个,则这个数肯定是丑数。
2.如果被判断的数能被2整除,则将这个数除以2,再进行循环判断;
3.如果被判断的数能被3整除,则将这个数除以3,再进行循环判断;
4.如果被判断的数能被5整除,则将这个数除以5,再进行循环判断;
5.如果被判断的数不能被2、3、5这三个数其中的一个整除,则这个数肯定不是丑数。
var isUgly = function(num) {
if(num <= 0) {
    return false
}
while(true){
    if(num == 1 || num == 2 || num == 3 || num ==5){
        return true
    }
    if(num % 2 == 0){
        num /= 2
    }else if(num % 3 == 0){
        num/=3
    }else if(num % 5 == 0){
        num /= 5 
    }else{
        return false
    }
}
};
function GetUglyNumber_Solution(index)
{
    // write code here
    let p2 = 1, p3 = 1, p5 = 1
    const dp = new Array(index+1)
    dp[0] = 0
    dp[1] = 1
    for(let i = 2;i<=index;i++){
        dp[i] = Math.min(dp[p2]*2, dp[p3]*3, dp[p5]*5)
        if(dp[i] == dp[p2]*2) p2++
        if(dp[i] == dp[p3]*3) p3++
        if(dp[i] == dp[p5]*5) p5++
    }
    return dp[index]
}
module.exports = {
    GetUglyNumber_Solution : GetUglyNumber_Solution
};



编辑于 2021-07-04 18:43:44 回复(0)
function isInterger(obj){
    return typeof obj == 'number' && obj%1 == 0;
}

function isUglyNumber(n){
//     console.log("isUglyNumber begin " + n)
    if(n < 1 || !isInterger(n)){
       return false;
    }
    if(n == 1 || n == 2 || n == 3 || n=== 4 || n == 5){
        return true;
    }
    var current = n;
    while(current > 5){
        if(isInterger(current/2)){
            current = current/2;
        }
        else if(isInterger(current/3)){
            current = current/3;
        }
        else if(isInterger(current/5)){
            current = current/5;
        }
        else{
            return false;
        }
    }
    if(isInterger(current)){
        return true;
    }
    return false;
}

function GetUglyNumber_Solution(index)
{
    // write code here
    var current = 0;
    var total = 0;
    while(total < index){
        if(isUglyNumber(current)){
            total++;
            if(total >= index){
                break;
            }
        }
        current++;
    }
    return current;
}

我这段代码有什么问题吗?大家指点一下
发表于 2021-01-08 00:23:26 回复(0)
function GetUglyNumber_Solution(index)
{
    if(index<7){
        return index
    }
    var res=[];
    res[0]=1;
    var t2=0,t3=0,t5=0;
    for(var i=1;i<index;i++){
        res[i]=Math.min(res[t2]*2,Math.min(res[t3]*3,res[t5]*5));
        if(res[i]===res[t2]*2)
            t2++;
        if(res[i]===res[t3]*3)
            t3++;
        if(res[i]===res[t5]*5)
            t5++;
    }
    return res[index-1]// write code here
}


发表于 2020-08-20 11:15:47 回复(0)
/**
 * 我的解题思路:
 * 1.既然每个丑数都能被2、3、5整除,那么就分别用这三个数去整除每一个数
 * 2.如果整除到最后的结果为1,那么说明这个数就是丑数,否则就继续找下一个数
 * 3.为了保证每次整除的结果不影响初始值,这里在整除前使用新的变量去操作
 * 4.这个方法很好理解,但是遗憾的是超时了
 * 
 * @param {*} index 
 */
function GetUglyNumber_Solution(index)
{
    // write code here
    let num = 1;
    let n = 1;
    const result = [];
    while (num !== index + 1) {
        let cur = n;
        while (cur % 2 === 0) {
            cur = cur / 2;
        }
        while (cur % 3 === 0) {
            cur = cur / 3;
        }
        while (cur % 5 === 0) {
            cur = cur / 5;
        }
        if (cur === 1) {
            num ++;
            result.push(n);
        }
        n ++;
    }
    return result[index - 1];
}

/**
 * 评论区TOP的解题思路:
 * 1.这个想法挺***的,前7个数就不用看了,直接看后面的思路
 * 2.第一个丑数是1,也就是当前index对应的最小丑数,那么我们用这个最小的丑数分别乘以2、3、5,就可以得到3个新的丑数
 * 3.在这三个新的丑数中,我们可以找到最小的,那么它就是下一个最小丑数,它对应的因子为当前最小因子
 * 4.我们用下一个最小丑数乘以当前最小因子之后与其他的两个丑数比较,再次获得一个最小丑数
 * 5.重复3、4步骤,我们就可以得到一个index长度的丑数序列,且按照从小到大排序
 * 6.最后返回数组中第index个丑数即可
 * 
 * @param {*} index 
 */
function topGetUglyNumber_Solution(index)
{
    // write code here
    if (index < 7) return index;
    const res = [1];
    let t2 = 0;
    let t3 = 0;
    let t5 = 0;
    for (let i = 1; i < index; i ++) {
        res[i] = Math.min(res[t2] * 2, Math.min(res[t3] * 3, res[t5] * 5));
        if (res[i] === res[t2] * 2) {
            t2 ++;
        }
        if (res[i] === res[t3] * 3) {
            t3 ++;
        }
        if (res[i] === res[t5] * 5) {
            t5 ++;
        }
    }
    return res[index - 1];
}

发表于 2020-06-08 21:47:24 回复(0)

解法同第一页高票回答

  • 维护三个指针,指向三个对应数组当前值
  • 质因子并非因数,比如8=2^3,不是8=2*4这样考虑的
function GetUglyNumber_Solution(index)
{
  // write code here
  // 小于7全是丑数
  if (index < 7) {
    return index;
  }

  let arr = [];
  // 维护三个指针,指向当前队列最小的数
  let p1 = 0, p2 = 0, p3 = 0;
  let newNum = 1;
  arr.push(newNum);

  while (arr.length < index) {
    newNum = Math.min(arr[p1] * 2, arr[p2] * 3, arr[p3] * 5);
    if (newNum === arr[p1] * 2) p1++;
    if (newNum === arr[p2] * 3) p2++;
    if (newNum === arr[p3] * 5) p3++;
    arr.push(newNum);
  }

  // console.log(arr);
  return arr[index - 1];
}

GetUglyNumber_Solution(16);
发表于 2019-09-03 11:22:26 回复(0)
只能被2、3、5整除,说明后面的丑数只能从前面的丑数*(2、3、5)中产生
简单做法:
1.每次把前面所有数*(2、3、5)
2.分别找到(2、3、5)*前面的数比当前最大丑数大的最小值
3.比较三个数取最小值加入到丑数队列中
优化:
1.前面的数不必每个都乘
2.记录下*(2、3、5)后刚好比当前最大丑数大的这三个值的下标 index2,index3,index5
3.下次比较从这 index2,index3,index5 三个下标开始乘起
4.最后取arr[index2]*2 arr[index3]*3 arr[index5]*5 的最小值

    function GetUglyNumber_Solution(index) {
      if (index <= 0) {
        return 0;
      }
      let arr = [1];
      let i2 = i3 = i5 = 0;
      let cur = 0;
      while (arr.length < index) {
        arr.push(Math.min(arr[i2] * 2, arr[i3] * 3, arr[i5] * 5));
        const current = arr[arr.length - 1];
        while (arr[i2] * 2 <= current) {
          i2++;
        }
        while (arr[i3] * 3 <= current) {
          i3++;
        }
        while (arr[i5] * 5 <= current) {
          i5++;
        }
      }
      return arr[index - 1];
    }

发表于 2019-02-24 11:24:04 回复(0)
从1开始,从小到大计算出每一个丑数,并存入数组。直到计算到第index个丑数时,输出。

function GetUglyNumber_Solution(index)
{
    //index小于1,则返回0
    if(index<1){
        return 0;
    }
    //index等于1,选择第1个丑数,返回”1“
    if(index==1){
        return 1;
    }
    
    var chou = [1];  //保存从小到大的丑数,第一个为1.
    var count=1;     //count用于计算当前已获得的丑数数量
    var two=0,three=0,five=0;  //用于作为计算丑数的因子,第一个丑数1不与2、3、5相乘,所以2、3、5初始化为0
    var i=1;
    //while循环,直到计算到第index个丑数时结束
    while(count < index){
        //在第一个丑数的基础上,分别乘以因子2、3、5,然后选出其中最小的一个数存入number。
        var number = Math.min(chou[two]*2,chou[three]*3,chou[five]*5);
        //number为丑数乘以2得到的
        if(number == chou[two]*2){
            two++;
        }
        //number为丑数乘以3得到的
        if(number == chou[three]*3){
            three++;
        }
        //number为丑数乘以5得到的
        if(number == chou[five]*5){
            five++;
        }
        //将丑数写入数组,count加1
        chou[i++] = number;
        count++;
    }
    return chou[i-1];
}

发表于 2018-05-29 14:14:47 回复(0)
function GetUglyNumber_Solution(index)
{
    // write code here
    var arr = [1];
    var i = 0;
    if(index <= 0){
        return 0;
    }else if(index === 1){
        return arr;
    }else{
        while(arr.length < index) {
            var M2 = 0;
            var M3 = 0;
            var M5 = 0;
            var i = 0;
            var j = 0;
            var k = 0;
            var M = arr[arr.length - 1];
            while (i < arr.length && M2 <= M) {
                M2 = arr[i] * 2;
                i++;
            }
            while (j < arr.length && M3 <= M) {
                M3 = arr[j] * 3;
                j++;
            }
            while (k < arr.length && M5 <= M) {
                M5 = arr[k] * 5;
                k++;
            }
            var temp = Math.min(M2,M3,M5);
            arr.push(temp)
        }
        return arr[arr.length-1]
    }
}

发表于 2018-05-10 10:03:38 回复(0)
function GetUglyNumber_Solution(index)
{
    if(index <=0) return 0;
    let uglyArr = [1], idx2 = idx3 = idx5 = 0, i;
    for(i = 1; i < index; ++i){
        uglyArr[i] = Math.min(uglyArr[idx2]*2, uglyArr[idx3]*3, uglyArr[idx5]*5);
        if(uglyArr[i] === uglyArr[idx2]*2) ++idx2;
        if(uglyArr[i] === uglyArr[idx3]*3) ++idx3;
        if(uglyArr[i] === uglyArr[idx5]*5) ++idx5;
    }
    return uglyArr[index-1];
}

发表于 2018-04-25 11:22:59 回复(0)
function GetUglyNumber_Solution(index)
{
    if(index == 0){
        return 0;
    }
    var arr = new Array(index);
    arr[0] = 1;
    var fac2 = 0,
        fac3 = 0,
        fac5 = 0;
    for(var i=1; i<arr.length; i++){
        var min = Math.min(arr[fac2]*2, arr[fac3]*3, arr[fac5]*5);
        arr[i] = min;
        while(arr[fac2]*2 <= min){
            fac2++;
        }
        while(arr[fac3]*3 <= min){
            fac3++;
        }
        while(arr[fac5]*5 <= min){
            fac5++;
        }
    }
    return arr[arr.length-1];
}

发表于 2017-09-10 19:28:20 回复(0)

问题信息

难度:
13条回答 135243浏览

热门推荐

通过挑战的用户

查看代码
丑数