leetcode - ugly number, ugly number2, super ugly number

来源:互联网 发布:胡歌的电视剧 知乎 编辑:程序博客网 时间:2024/05/16 13:38

Problems:
1、
Write a program to check whether a given number is an ugly number.

Ugly numbers are positive numbers whose prime factors only include 2, 3, 5. For example, 6, 8 are ugly while 14 is not ugly since it includes another prime factor 7.

Note that 1 is typically treated as an ugly number.
2、
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.
3、
Write a program to find the nth super ugly number.

Super ugly numbers are positive numbers whose all prime factors are in the given prime list primes of size k. For example, [1, 2, 4, 7, 8, 13, 14, 16, 19, 26, 28, 32] is the sequence of the first 12 super ugly numbers given primes = [2, 7, 13, 19] of size 4.

Note:
(1) 1 is a super ugly number for any given primes.
(2) The given numbers in primes are in ascending order.
(3) 0 < k ≤ 100, 0 < n ≤ 106, 0 < primes[i] < 1000.

Solution:
这三个问题是层层递进的:
1、这个很容易,只要能整除,就用given number一直除以prime factors,当不能整除时,given number值为1 即是 ugly number;

2、有两个思路:
一个是简单思维,基于问题1,按照1,2,3,4…的顺序,依次往下找出ugly number,直到找到第n个ugly number为止。这个方式要计算太多无意义的数,浪费时间;
二是巧妙思维,对于一个ugly number,一定是前面的ugly number乘以prime factors中最小的一个。
当然有多种实现方法:
(1)每个primes[i] *{1,2,3,4…}作为一个链表(一定是从小到大排列),取出所有链表中的第一个(一定是该链表中最小的)并找出最小的一个丢出来,计入Ugly number。不断重复这个过程,直到找到第n个。
(2)只需要ugly number这一个数组即可。
思路如下:
申请一个长度为n的数组uglyNumber,用于从小到大顺序存储n个丑数,数组中的首项第一个丑数:1;
设置三个变量id2、id3、id5存储下标,初始值都为0;找出数组uglyNumbers[id2]*2、uglyNumbers[id3]*3、uglyNumbers[id5]*5的最小值,最小值即为下一个丑数,同时更新最小值对应的下标,如果多个数字同时为最小值,则它们的下标都要更新;找到第n个丑数时,循环结束

(3)用Java:
SortedSet s1 = new TreeSet<>(); 每次取出第一个即最小的一个,再根据最小的一个加入新生成的数。

3、根据第二题很容易就能做到了
这里有几个tips:
new int[]:会自动初始化,数组中所有值为1;
找出最小值后,所有等于这个最小值的数的下标都要+1是为了防止ugly number的数组中有重复值出现,而在这里,实现这个思路需要进行一次遍历,浪费时间。那么换个思路,为了防止重复出现,只需要将得到的第i个uglynum和uglynum中第i-1个数进行比较,如果相等就跳过即可。

三个题目代码如下:
1、

public class Solution {    public boolean isUgly(int num) {        if(num == 0)   return false;        if(num == 1)   return true;        while(num%2 == 0){            num = num/2;        }        while(num%3 == 0){            num = num/3;        }        while(num%5 == 0){            num = num/5;        }        if(num == 1){         return true;        }else{            return false;        }    }}

2、选择第二种思路

public class Solution {    public int nthUglyNumber(int n) {        if(n==1) return 1;        int[] uglynum = new int[n]; uglynum[0] = 1;        int i = 0, j = 0, k = 0,count = 1;        while(count < n ){            int min = minimum(uglynum[i]*2,uglynum[j]*3,uglynum[k]*5);            uglynum[count] = min;            if(min == uglynum[i]*2) i++;            if(min == uglynum[j]*3) j++;            if(min == uglynum[k]*5) k++;            count ++;        }        return uglynum[n-1];    }    public int minimum(int i,int j, int k){        int flag = i<j?i:j;        return flag<k?flag:k;    }}

3、这里是将所有等于min的数下标全部+1,因此多了次遍历

public class Solution {    public int nthSuperUglyNumber(int n, int[] primes) {        if(n == 1) return 1;        int[] uglynum = new int[n];        int[] primesnum = new int[primes.length];        //初始化默认全部为0        int[] pointsnum = new int [primes.length];        uglynum[0] = 1;        int flag = 1, min = 1;        while(flag < n){            for(int j = 0 ; j < primes.length ; j++){                primesnum[j] = uglynum[pointsnum[j]] * primes[j];            }            min = findmin(primesnum,pointsnum);            uglynum [flag] = min;            flag ++ ;        }        return min;    }    public int findmin(int[] primesnum , int[] pointsnum){        int min = primesnum[0];        for(int i = 1 ; i < primesnum.length ; i++){           min  = primesnum[i] < min? primesnum[i]:min;        }        for(int i = 0; i< primesnum.length ; i++){            if(primesnum[i] == min)  pointsnum[i]++;        }        return min;    }}

当然,关于最后一个遍历希望大家多提提建议,应该有更简单的方法!

0 0
原创粉丝点击