Leetcode 263. Ugly Number & 264. Ugly Number II

来源:互联网 发布:银天下行情分析软件 编辑:程序博客网 时间:2024/05/16 15:39

263. Ugly Number

Total Accepted: 58196 Total Submissions: 157221 Difficulty: Easy

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,3,5之后等于1便是ugly number。然而:

public class Solution { // TLE at 905391974    public boolean isUgly(int num) {        if(num<=0) return false;        if(num==1) return true;        int base = 2;        while(num>1){            if(num%base==0){                if(base>5) return false;                num/=base;            }else{                base++;            }        }        return true;    }}

博主看了看例子,应该是因为寻找下一个可以除的base的时间太长了。于是修改了一下:

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

瞬间AC, 3MS.


网上的标准版本是2MS:

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


264. Ugly Number II

Total Accepted: 41874 Total Submissions: 136798 Difficulty: Medium

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.

Hint:

1. The naive approach is to call isUgly for every number until you reach the nth one. Most numbers are not ugly. Try to focus your effort on 
generating only the ugly ones.
2. An ugly number must be multiplied by either 2, 3, or 5 from a smaller ugly number.
3. The key is how to maintain the order of the ugly numbers. Try a similar approach of merging from three sorted lists: L1, L2, and L3.
4. Assume you have Uk, the kth ugly number. Then Uk+1 must be Min(L1 * 2, L2 * 3, L3 * 5).

Credits:
Special thanks to @jianchao.li.fighter for adding this problem and creating all test cases.

思路一:

对每个数调用isUgly函数,直到第n个。


思路二:

丑陋数序列可以拆分为下面3个子列表:

(1) 1×2, 2×2, 3×2, 4×2, 5×2, …(2) 1×3, 2×3, 3×3, 4×3, 5×3, …(3) 1×5, 2×5, 3×5, 4×5, 5×5, …
我们可以发现每一个子列表都是丑陋数本身(1, 2, 3, 4, 5, …) 乘以 2, 3, 5

接下来我们使用与归并排序相似的合并方法,从3个子列表中获取丑陋数。每一步我们从中选出最小的一个,然后向后移动一步。


这里有个问题,如果直接用LinkedList<Integer>不会溢出,但是PriorityQueue<Integer>就不行,得用<Long>

public class Solution {  // 79 ms    public int nthUglyNumber(int n) {          long u = 0L;          PriorityQueue<Long> q1 = new PriorityQueue<Long>();          PriorityQueue<Long> q2 = new PriorityQueue<Long>();          PriorityQueue<Long> q3 = new PriorityQueue<Long>();          q1.add(1L);          q2.add(1L);          q3.add(1L);                    for(int i=0; i<n; i++) {              u = Math.min( Math.min(q1.peek(), q2.peek()), q3.peek());                            if(q1.peek() == u) q1.poll();              if(q2.peek() == u) q2.poll();              if(q3.peek() == u) q3.poll();                            q1.add(u*2);              q2.add(u*3);              q3.add(u*5);          }          return (int) u;      }  }  

public class Solution {  // 74ms    public int nthUglyNumber(int n) {          int u = 0;          List<Integer> l1 = new LinkedList<Integer>();          List<Integer> l2 = new LinkedList<Integer>();          List<Integer> l3 = new LinkedList<Integer>();          l1.add(1);          l2.add(1);          l3.add(1);                    for(int i=0; i<n; i++) {              u = Math.min( Math.min(l1.get(0), l2.get(0)), l3.get(0));                            if(l1.get(0) == u) l1.remove(0);              if(l2.get(0) == u) l2.remove(0);              if(l3.get(0) == u) l3.remove(0);                            l1.add(u*2);              l2.add(u*3);              l3.add(u*5);          }          return u;      }  }  

进阶版:

用DP保存第i个Ugly Number,然后用3个指针指向当前的位置。

比如第一个ugly number是1,那么3个指针都指向0位置。判断的时候取res[p1]*2, res[p2]*3和res[p3]*5的最小值。

之后再移动相应指针一位。

一开始都指向1(res[0]),然后min取到的是2,所以p2目前指向res[1] = 2。这样下次对比就是( 2*2, 1*3, 1*5)来对比,结果放入res[2]。

public class Solution { // 10ms   public int nthUglyNumber(int n) {        if( n == 0 || n == 1) {        return n;    }        int pointer2 = 0;    int pointer3 = 0;    int pointer5 = 0;        int[] result = new int[n];    result[0] = 1;    int i = 1, min =0;    while ( i < n ) {        min = Math.min(result[pointer2]*2,Math.min(result[pointer3]*3,result[pointer5]*5));                if(min == result[pointer2]*2) {            pointer2++;        }        if(min == result[pointer3]*3) {            pointer3++;        }        if(min == result[pointer5]*5) {            pointer5++;        }        result[i] = min;             i++;            }    return result[n-1];    }}


0 0