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. LeetCode LCP 3 机器人大冒险

    题目解析: 对于本题主要的核心是对于一个指令字符串如“RURUU”,如果我们假设它的终点坐标为(8,8),其实只要统计指令字符串中的R的个数和U的个数(对于我给出的例子而言,num_R == 2,nu ...

  2. less-3

    首先来了解语句构造方法: 我们输入id=1可以看到未报错,输入id=1’报错,输入id=1’’未报错. 再对比下之前我们在less-1中的报错信息(如下图),可以看到,在less-3中报错信息中“1” ...

  3. hdu1171&&P2000——母函数

    hdu1171 题意:有 $n$ 种设施,每种有价值 $v_i$ 和数量 $m_i$,求一种方案使得分成价值尽可能相近的两组.($n \leq 50, v_i \leq 50, m_i \leq 10 ...

  4. Codeforces Round #605 (Div. 3) D. Remove One Element(DP)

    链接: https://codeforces.com/contest/1272/problem/D 题意: You are given an array a consisting of n integ ...

  5. JavaScript基础03——函数的作用域及变量提升

    1.作用域 作用域,变量在函数内部作用的范围/区域.有函数的地方就有作用域.   2.局部作用域和全局作用域 function fn(){ var a = 1; } console.log(a); / ...

  6. 002——keil-Error: L6915E: Library reports error: __use_no_semihosting was requested解决

    ..\OBJ\KEY.axf: Error: L6915E: Library reports error: __use_no_semihosting was requested, but _ttywr ...

  7. 详解如何在CentOS7中使用Nginx和PHP7-FPM安装Nextcloud

    转载地址:https://www.jb51.net/article/109382.htm 这篇文章主要介绍了详解如何在CentOS7中使用Nginx和PHP7-FPM安装Nextcloud,会通过 N ...

  8. MySQL 开启慢查询日志与普通日志

    一.开启满查询日志 1.查看慢查询日志 SHOW VARIABLES LIKE '%slow%'; 2.开启慢查询日志 set GLOBAL slow_query_log =on; 3.设置慢查询日志 ...

  9. [转]查看 docker 容器使用的资源

    作者:sparkdev 出处:http://www.cnblogs.com/sparkdev/     在容器的使用过程中,如果能及时的掌握容器使用的系统资源,无论对开发还是运维工作都是非常有益的.幸 ...

  10. 刷题记录:[CISCN2019 东北赛区 Day2 Web3]Point System

    目录 刷题记录:[CISCN2019 东北赛区 Day2 Web3]Point System 知识点 1.padding-oracle attack 2.cbc字节翻转攻击 3.FFMpeg文件读取漏 ...