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.

Example:

Input: n = 12, primes = [2,7,13,19]
Output: 32
Explanation: [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 is a super ugly number for any given primes.
  • The given numbers in primes are in ascending order.
  • 0 < k ≤ 100, 0 < n ≤ 106, 0 < primes[i] < 1000.
  • The nth super ugly number is guaranteed to fit in a 32-bit signed integer.

264. Ugly Number II 的拓展,还是找出第n个丑陋数,但质数集合不在只是2,3,5,而是可以任意给定。难度增加了,但本质上和Ugly Number II 没有什么区别,由于不知道质数的个数,可以用一个idx数组来保存当前的位置,然后从每个子链中取出一个数,找出其中最小值,然后更新idx数组对应位置,注意有可能最小值不止一个,要更新所有最小值的位置。

解题思路:
要使得super ugly number不漏掉,那么需要使用每个因子去乘以其对应的“第一个”丑数。那么何为对应的“第一个”丑数?

首先,利用ugly[]数组来保存所有的超级丑数,ugly[i]表示第i+1个超级丑数;

接着利用pointer[]数组来表示每个因子对应的“第一个”丑数的下标。pointer数组长度当然需要和primes长度一致,且初始化为0,代表着每个因子对应的“第一个”丑数都是ugly[0];

接下来我们以primes[2,7,13,19],pointer[0,0,0,0],ugly[0]=1作为初始条件往下看:

遍历primes数组,用每个因子都乘以其对应的第一个丑数,即ugly[0]=1,可以发现1x2=2是最小值,故ugly[1]=2;但要注意,此时的pointer数组发生了变化:

由于当前产生的丑数2是由2这个因子乘以它的对应“第一个”丑数得到的,因此需要将pointer[0]加一。pointer[0]是2这个因子对应的“第一个”丑数的下标,因为当前已经使用了2x1,如果不更新,则下一轮还是会用2这个因子去乘以第一个丑数(ugly[0]).将其更新后,则意味着2这个因子对应的第一个丑数已经改变了,变成了ugly[1].而其他三个对应的“第一个”丑数还是ugly[0]。

我们接着看下一轮:2x2【即ugly[pointer[1]]x2】,1x7,1x13,1x19,发现还是2这个因子得到的数最小,故更新:ugly[2]=2x2=4,pointer[0]=2;

下一轮:4x2,1x7,1x13,1x19,可以发现当前这一轮最小值是7,且由因子7产生,故更新:ugly[3]=7,pointer[1]=1;

以此类推....
如果更新过程中,出现最小值不止一个的话,则其对应的pointer的值都需要增加1。

Java:

public int nthSuperUglyNumber(int n, int[] primes) {
int[] ugly = new int[n+1];
ugly[0]=1;
int[] pointer = new int[primes.length];
for(int i=1;i<n;i++) {
int min=Integer.MAX_VALUE;
int minIndex = 0;
for(int j=0;j<primes.length;j++) {
if(ugly[pointer[j]]*primes[j]<min) {
min=ugly[pointer[j]]*primes[j];
minIndex = j;
}else if(ugly[pointer[j]]*primes[j]==min) {
pointer[j]++;
}
}
ugly[i]=min;
pointer[minIndex]++;
}
return ugly[n-1];
}

Java:1

public int nthSuperUglyNumberI(int n, int[] primes) {
int[] ugly = new int[n];
int[] idx = new int[primes.length]; ugly[0] = 1;
for (int i = 1; i < n; i++) {
//find next
ugly[i] = Integer.MAX_VALUE;
for (int j = 0; j < primes.length; j++)
ugly[i] = Math.min(ugly[i], primes[j] * ugly[idx[j]]); //slip duplicate
for (int j = 0; j < primes.length; j++) {
while (primes[j] * ugly[idx[j]] <= ugly[i]) idx[j]++;
}
} return ugly[n - 1];
}

Java:2

public int nthSuperUglyNumber(int n, int[] primes) {
int[] ugly = new int[n];
int[] idx = new int[primes.length];
int[] val = new int[primes.length];
Arrays.fill(val, 1); int next = 1;
for (int i = 0; i < n; i++) {
ugly[i] = next; next = Integer.MAX_VALUE;
for (int j = 0; j < primes.length; j++) {
//skip duplicate and avoid extra multiplication
if (val[j] == ugly[i]) val[j] = ugly[idx[j]++] * primes[j];
//find next ugly number
next = Math.min(next, val[j]);
}
} return ugly[n - 1];
}

Java: 3 index heap 

public int nthSuperUglyNumberHeap(int n, int[] primes) {
int[] ugly = new int[n]; PriorityQueue<Num> pq = new PriorityQueue<>();
for (int i = 0; i < primes.length; i++) pq.add(new Num(primes[i], 1, primes[i]));
ugly[0] = 1; for (int i = 1; i < n; i++) {
ugly[i] = pq.peek().val;
while (pq.peek().val == ugly[i]) {
Num nxt = pq.poll();
pq.add(new Num(nxt.p * ugly[nxt.idx], nxt.idx + 1, nxt.p));
}
} return ugly[n - 1];
} private class Num implements Comparable<Num> {
int val;
int idx;
int p; public Num(int val, int idx, int p) {
this.val = val;
this.idx = idx;
this.p = p;
} @Override
public int compareTo(Num that) {
return this.val - that.val;
}
} 

Python:

def nthSuperUglyNumber(self, n, primes):
ugly = [1]
pointers = [0]*len(primes) for i in range(1,n):
minu = float("inf")
minIndex = 0
for j in range(len(primes)):
if primes[j] * ugly[pointers[j]] < minu:
minu = primes[j] * ugly[pointers[j]]
minIndex = j
elif primes[j] * ugly[pointers[j]] == minu:
pointers[j] += 1
ugly.append(minu)
pointers[minIndex] += 1
return ugly[-1]  

Python:

# Heap solution. (620ms)
class Solution(object):
def nthSuperUglyNumber(self, n, primes):
"""
:type n: int
:type primes: List[int]
:rtype: int
"""
heap, uglies, idx, ugly_by_last_prime = [], [0] * n, [0] * len(primes), [0] * n
uglies[0] = 1 for k, p in enumerate(primes):
heapq.heappush(heap, (p, k)) for i in xrange(1, n):
uglies[i], k = heapq.heappop(heap)
ugly_by_last_prime[i] = k
idx[k] += 1
while ugly_by_last_prime[idx[k]] > k:
idx[k] += 1
heapq.heappush(heap, (primes[k] * uglies[idx[k]], k)) return uglies[-1]

Python:

# Time:  O(n * k)
# Space: O(n + k)
# Hash solution. (932ms)
class Solution2(object):
def nthSuperUglyNumber(self, n, primes):
"""
:type n: int
:type primes: List[int]
:rtype: int
"""
uglies, idx, heap, ugly_set = [0] * n, [0] * len(primes), [], set([1])
uglies[0] = 1 for k, p in enumerate(primes):
heapq.heappush(heap, (p, k))
ugly_set.add(p) for i in xrange(1, n):
uglies[i], k = heapq.heappop(heap)
while (primes[k] * uglies[idx[k]]) in ugly_set:
idx[k] += 1
heapq.heappush(heap, (primes[k] * uglies[idx[k]], k))
ugly_set.add(primes[k] * uglies[idx[k]]) return uglies[-1]

Python:  

# Time:  O(n * logk) ~ O(n * klogk)
# Space: O(n + k)
class Solution3(object):
def nthSuperUglyNumber(self, n, primes):
"""
:type n: int
:type primes: List[int]
:rtype: int
"""
uglies, idx, heap = [1], [0] * len(primes), []
for k, p in enumerate(primes):
heapq.heappush(heap, (p, k)) for i in xrange(1, n):
min_val, k = heap[0]
uglies += [min_val] while heap[0][0] == min_val: # worst time: O(klogk)
min_val, k = heapq.heappop(heap)
idx[k] += 1
heapq.heappush(heap, (primes[k] * uglies[idx[k]], k)) return uglies[-1]    

C++:

class Solution {
public:
int nthSuperUglyNumber(int n, vector<int>& primes) {
vector<int> res(1, 1), idx(primes.size(), 0);
while (res.size() < n) {
vector<int> tmp;
int mn = INT_MAX;
for (int i = 0; i < primes.size(); ++i) {
tmp.push_back(res[idx[i]] * primes[i]);
}
for (int i = 0; i < primes.size(); ++i) {
mn = min(mn, tmp[i]);
}
for (int i = 0; i < primes.size(); ++i) {
if (mn == tmp[i]) ++idx[i];
}
res.push_back(mn);
}
return res.back();
}
};

C++:  

class Solution {
public:
int nthSuperUglyNumber(int n, vector<int>& primes) {
vector<int> dp(n, 1), idx(primes.size(), 0);
for (int i = 1; i < n; ++i) {
dp[i] = INT_MAX;
for (int j = 0; j < primes.size(); ++j) {
dp[i] = min(dp[i], dp[idx[j]] * primes[j]);
}
for (int j = 0; j < primes.size(); ++j) {
if (dp[i] == dp[idx[j]] * primes[j]) {
++idx[j];
}
}
}
return dp.back();
}
};

  

类似题目:

[LeetCode] 263. Ugly Number 丑陋数

[LeetCode] 264. Ugly Number II 丑陋数 II

All LeetCode Questions List 题目汇总

[LeetCode] 313. Super Ugly Number 超级丑陋数的更多相关文章

  1. [LeetCode]313. Super Ugly Number超级丑数,丑数系列看这一道就行了

    丑数系列的题看这一道就可以了 /* 和ugly number2差不多,不过这次的质因子多了,所以用数组来表示质因子的target坐标 target坐标指的是这个质因子此次要乘的前任丑数是谁 */ pu ...

  2. [LeetCode] Super Ugly Number 超级丑陋数

    Write a program to find the nth super ugly number. Super ugly numbers are positive numbers whose all ...

  3. [LintCode] Super Ugly Number 超级丑陋数

    Write a program to find the nth super ugly number. Super ugly numbers are positive numbers whose all ...

  4. 313 Super Ugly Number 超级丑数

    编写一段程序来寻找第 n 个超级丑数.超级丑数是指其所有质因数都在长度为k的质数列表primes中的正整数.例如,[1, 2, 4, 7, 8, 13, 14, 16, 19, 26, 28, 32] ...

  5. Leetcode 313. super ugly number

    Write a program to find the nth super ugly number. Super ugly numbers are positive numbers whose all ...

  6. [LeetCode] 264. Ugly Number II 丑陋数 II

    Write a program to find the n-th ugly number. Ugly numbers are positive numbers whose prime factors ...

  7. leetcode 263. Ugly Number 、264. Ugly Number II 、313. Super Ugly Number 、204. Count Primes

    263. Ugly Number 注意:1.小于等于0都不属于丑数 2.while循环的判断不是num >= 0, 而是能被2 .3.5整除,即能被整除才去除这些数 class Solution ...

  8. [LeetCode] Ugly Number II 丑陋数之二

    Write a program to find the n-th ugly number. Ugly numbers are positive numbers whose prime factors ...

  9. [LeetCode] 264. Ugly Number II 丑陋数之二

    Write a program to find the n-th ugly number. Ugly numbers are positive numbers whose prime factors ...

随机推荐

  1. WPF 控件库——带有惯性的ScrollViewer*(转)

    转:https://blog.csdn.net/ahilll/article/details/82418892 一.先看看效果 二.原理 虽然效果很简单,但是网上的一些资料涉及的代码量非常可观,而且效 ...

  2. c#2.0锐利体验《泛型编程》读书笔记

    1.c#泛型及机制 Class Stack<T> { } T 其实为type的缩小,不过也可为其他字符代替T ,被称为“泛型类型”  T为晚绑定的,在编译的时候还不能确定T的确切类型. 2 ...

  3. 自用 goodsdetail

    JSON.parse(data.parameter)  存的字符串 <select id="getGoodsBaseInfoById" resultType="co ...

  4. webuploader解决大文件断点续传

    文件夹数据库处理逻辑 public class DbFolder { JSONObject root; public DbFolder() { this.root = new JSONObject() ...

  5. 【批处理】choice命令,call 命令,start 命令,rem

    [1]choice命令简介 使用此命令可以提示用户输入一个选择项,根据用户输入的选择项再决定执行具体的过程. 使用时应该加/c:参数,c: 后应写提示可输入的字符或数字,之间无空格.冒号是可选项. 使 ...

  6. scylladb docker-compose 用户密码认证配置

    scylladb 对于用户的认证配置还是比较简单的,以下是一个docker-compose 配置的说明 环境准备 docker-compose 文件 version: "3" se ...

  7. 在触发器中使用{ITEM.LASTVALUE}时在首页问题栏信息显示不全

    在触发器中使用了系统宏变量,当条件满足时,如果这个宏代表的内容超过了20个字符,那么在首页信息就显示不全,会有一堆省略号 感谢https://blog.csdn.net/yu415907917/art ...

  8. 漏斗分析(Funnel Analysis)

    什么是漏斗分析? 简单来讲,就是抽象出某个流程,观察流程中每一步的转化与流失. 漏斗的三个要素: 时间:特指漏斗的转化周期,即为完成每一层漏斗所需时间的集合 节点:每一层漏斗,就是一个节点 流量:就是 ...

  9. python3 报错UnicodeEncodeError

    在ubuntu执行python3的时候,出现 UnicodeEncodeError: 'latin-1' codec can't encode characters in position 10-18 ...

  10. 【牛客】小w的魔术扑克 (并查集?? 树状数组)

    题目描述 小w喜欢打牌,某天小w与dogenya在一起玩扑克牌,这种扑克牌的面值都在1到n,原本扑克牌只有一面,而小w手中的扑克牌是双面的魔术扑克(正反两面均有数字,可以随时进行切换),小w这个人就准 ...