LeetCode--263. Ugly Number & 264. Ugly Number II
阿新 • • 發佈:2019-01-13
問題連結:https://leetcode.com/problems/ugly-number/和https://leetcode.com/problems/ugly-number-ii/
關於醜陋數,問題比較簡單,問題二也不難,但值得研究研究。
問題一思路:比較直接沒啥好說的,注意醜陋數為正數
class Solution { public boolean isUgly(int num) { if(num<=0) return false; while(num>1) { if(num%2==0) { num/=2; } else if(num%3==0) { num/=3; } else if(num%5==0) { num/=5; } else return false; } return true; } }
問題二:優先佇列加雜湊集合,注意乘法運算溢位的問題,這裡使用Long型
class Solution { public static int nthUglyNumber(int n) { PriorityQueue<Long> pq=new PriorityQueue<>(); HashSet<Long> set=new HashSet<>(); set.add(new Long(1)); pq.add(new Long(1)); Long ret=new Long(1); for(int i=1;i<=n;i++) { ret=pq.poll(); if(set.add(ret*2)) pq.add(ret*2); if(set.add(ret*3)) pq.add(ret*3); if(set.add(ret*5)) pq.add(ret*5); } return ret.intValue(); } }
因為使用了優先佇列和集合操作,時間複雜度為O(nlogK),這個效率比較低。
當然上面的思路還可以優化一下,不需要使用集合來判重,程式碼如下:
public int nthUglyNumber(int n) { if(n==1) return 1; PriorityQueue<Long> q = new PriorityQueue(); q.add(1l); for(long i=1; i<n; i++) { long tmp = q.poll(); while(!q.isEmpty() && q.peek()==tmp) tmp = q.poll(); q.add(tmp*2); q.add(tmp*3); q.add(tmp*5); } return q.poll().intValue(); }
其實使用TreeSet可以實現優先佇列和集合的功能:
public class Solution {
public int nthUglyNumber(int n) {
TreeSet<Long> ans = new TreeSet<>();
ans.add(1L);
for (int i = 0; i < n - 1; ++i) {
long first = ans.pollFirst();
ans.add(first * 2);
ans.add(first * 3);
ans.add(first * 5);
}
return ans.first().intValue();
}
}
有沒有更簡潔的思路呢?Hint中提示了動態規劃的思路:
public int nthUglyNumber(int n) {
int[] res = new int[n];
res[0] = 1;
int t2 = 0, t3 = 0, t5 = 0, idx = 1;
while (idx < n) {
res[idx] = Math.min(res[t2] * 2, Math.min(res[t3] * 3, res[t5] * 5));
t2 += res[idx] == res[t2] * 2 ? 1 : 0;
t3 += res[idx] == res[t3] * 3 ? 1 : 0;
t5 += res[idx] == res[t5] * 5 ? 1 : 0;
++idx;
}
return res[n - 1];
}
時間和空間複雜度都為O(n),簡直clean and concise!