Super ugly numbers are positive numbers whose all prime factors are in the given prime list. Given a number n, the task is to find the nth Super Ugly number.
It may be assumed that a given set of primes is sorted. Also, the first Super Ugly number is 1 by convention.
Examples:
Input : primes[] = [2, 5]
n = 5
Output : 8
Super Ugly numbers with given prime factors
are 1, 2, 4, 5, 8, ...
Fifth Super Ugly number is 8
Input : primes[] = [2, 3, 5]
n = 50
Output : 243
Input : primes[] = [3, 5, 7, 11, 13]
n = 9
Output: 21
In our previous post, we discussed Ugly Number. This problem is basically an extension of Ugly Numbers.
A simple solution for this problem is to one by one pick each number starting from 1 and find it’s all primes factors, if all prime factors lie in the given set of primes that means the number is Super Ugly. Repeat this process until we get nth Super Ugly Number.
An efficient solution for this problem is similar to Method-2 of Ugly Number. Here is the algorithm:
- Let k be the size of a given array of prime numbers.
- Declare a set for super ugly numbers.
- Insert the first ugly number (which is always 1) into the set.
- Initialize array multiple_of[k] of size k with 0. Each element of this array is an iterator for the corresponding prime in primes[k] array.
- Initialize nextMultipe[k] array with primes[k]. This array behaves like next multiple variables of each prime in given primes[k] array i.e; nextMultiple[i] = primes[i] * ugly[++multiple_of[i]].
- Now loop until there are n elements in set ugly.
a). Find minimum among current multiples of primes in nextMultiple[] array and insert it in the set of ugly numbers.
b). Then find this current minimum is multiple of which prime.
c). Increase iterator by 1 i.e; ++multiple_Of[i], for next multiple of current selected prime and update nextMultiple for it.
Below is the implementation of the above steps.
CPP
#include<bits/stdc++.h>
using namespace std;
int superUgly( int n, int primes[], int k)
{
vector< int > nextMultiple(primes, primes+k);
int multiple_Of[k];
memset (multiple_Of, 0, sizeof (multiple_Of));
set< int > ugly;
ugly.insert(1);
while (ugly.size() != n)
{
int next_ugly_no = *min_element(nextMultiple.begin(),
nextMultiple.end());
ugly.insert(next_ugly_no);
for ( int j=0; j<k; j++)
{
if (next_ugly_no == nextMultiple[j])
{
multiple_Of[j]++;
set< int >::iterator it = ugly.begin();
for ( int i=1; i<=multiple_Of[j]; i++)
it++;
nextMultiple[j] = primes[j] * (*it);
break ;
}
}
}
set< int >::iterator it = ugly.end();
it--;
return *it;
}
int main()
{
int primes[] = {2, 5};
int k = sizeof (primes)/ sizeof (primes[0]);
int n = 5;
cout << superUgly(n, primes, k);
return 0;
}
|
Java
import java.util.*;
class Main {
public static void main(String[] args)
{
int [] primes = { 2 , 5 };
int k = primes.length;
int n = 5 ;
System.out.println(superUgly(n, primes, k));
}
public static int superUgly( int n, int [] primes, int k)
{
int [] nextMultiple = Arrays.copyOf(primes, k);
int [] multiple_Of = new int [k];
Arrays.fill(multiple_Of, 0 );
Set<Integer> ugly = new HashSet<>();
ugly.add( 1 );
while (ugly.size() != n) {
int next_ugly_no = Integer.MAX_VALUE;
for ( int i = 0 ; i < k; i++) {
next_ugly_no = Math.min(next_ugly_no,
nextMultiple[i]);
}
ugly.add(next_ugly_no);
for ( int j = 0 ; j < k; j++) {
if (next_ugly_no == nextMultiple[j]) {
multiple_Of[j]++;
List<Integer> uglyList
= new ArrayList<>(ugly);
int it
= uglyList.get(multiple_Of[j] - 1 );
nextMultiple[j] = primes[j] * it;
break ;
}
}
}
List<Integer> uglyList = new ArrayList<>(ugly);
return uglyList.get(uglyList.size() - 1 );
}
}
|
Python3
from typing import List
def superUgly(n: int , primes: List [ int ], k: int ) - > int :
nextMultiple = primes[:]
multiple_Of = [ 0 ] * k
ugly = set ([ 1 ])
while len (ugly) ! = n:
next_ugly_no = min (nextMultiple)
ugly.add(next_ugly_no)
for j in range (k):
if next_ugly_no = = nextMultiple[j]:
multiple_Of[j] + = 1
it = sorted (ugly)[multiple_Of[j]]
nextMultiple[j] = primes[j] * it
break
return max (ugly)
if __name__ = = '__main__' :
primes = [ 2 , 5 ]
k = len (primes)
n = 5
print (superUgly(n, primes, k))
|
C#
using System;
using System.Collections.Generic;
class MainClass {
public static void Main( string [] args)
{
int [] primes = { 2, 5 };
int k = primes.Length;
int n = 5;
Console.WriteLine(superUgly(n, primes, k));
}
public static int superUgly( int n, int [] primes, int k)
{
int [] nextMultiple = new int [k];
Array.Copy(primes, nextMultiple, k);
int [] multiple_Of = new int [k];
Array.Fill(multiple_Of, 0);
HashSet< int > ugly = new HashSet< int >();
ugly.Add(1);
while (ugly.Count != n) {
int next_ugly_no = Int32.MaxValue;
for ( int i = 0; i < k; i++) {
next_ugly_no = Math.Min(next_ugly_no,
nextMultiple[i]);
}
ugly.Add(next_ugly_no);
for ( int j = 0; j < k; j++) {
if (next_ugly_no == nextMultiple[j]) {
multiple_Of[j]++;
List< int > uglyList
= new List< int >(ugly);
int it = uglyList[multiple_Of[j] - 1];
nextMultiple[j] = primes[j] * it;
break ;
}
}
}
List< int > finalUglyList = new List< int >(ugly);
return finalUglyList[finalUglyList.Count - 1];
}
}
|
Javascript
function superUgly(n, primes, k) {
let nextMultiple = primes.slice();
let multipleOf = new Array(k).fill(0);
let ugly = new Set();
ugly.add(1);
while (ugly.size !== n) {
let nextUglyNo = Math.min(...nextMultiple);
ugly.add(nextUglyNo);
for (let j = 0; j < k; j++) {
if (nextUglyNo === nextMultiple[j]) {
multipleOf[j]++;
let it = ugly.values();
for (let i = 1; i <= multipleOf[j]; i++)
it.next();
nextMultiple[j] = primes[j] * it.next().value;
break ;
}
}
}
let result = Array.from(ugly).pop();
return result;
}
let primes = [2, 5];
let k = primes.length;
let n = 5;
console.log(superUgly(n, primes, k));
|
This article is contributed by Shashank Mishra .
Another method (using priority_queue)
Here we use min heap priority_queue.
The idea is to push the first ugly no. which is 1 into priority_queue and at every iteration take the top of priority_queue and push all the multiples of that top into priority_queue.
Assuming a[] = {2, 3, 5},
so at first iteration 1 is top so 1 is popped and 1 * 2, 1 * 3, 1 * 5 is pushed.
At second iteration min is 2, so it is popped and 2 * 2, 2 * 3, 2 * 5 is pushed and so on.
Implementation:
CPP
#include<bits/stdc++.h>
using namespace std;
int ugly( int a[], int size, int n){
if (n <= 0)
return -1;
if (n == 1)
return 1;
priority_queue< int , vector< int >, greater< int >> pq;
for ( int i = 0; i < size; i++){
pq.push(a[i]);
}
int count = 1, no;
while (count < n){
no = pq.top();
pq.pop();
if (no != pq.top())
{
count++;
for ( int i = 0; i < size; i++){
pq.push(no * a[i]);
}
}
}
return no;
}
int main(){
int a[3] = {2, 3,5};
int size = sizeof (a) / sizeof (a[0]);
cout << ugly(a, size, 10)<<endl;
return 0;
}
|
Java
import java.util.PriorityQueue;
public class SuperUglyNumber {
public static int ugly( int [] a, int size, int n) {
if (n <= 0 )
return - 1 ;
if (n == 1 )
return 1 ;
PriorityQueue<Integer> pq = new PriorityQueue<Integer>();
for ( int i = 0 ; i < size; i++){
pq.add(a[i]);
}
int count = 1 , no = 0 ;
while (count < n){
no = pq.poll();
if (no != pq.peek())
{
count++;
for ( int i = 0 ; i < size; i++){
pq.add(no * a[i]);
}
}
}
return no;
}
public static void main(String[] args) {
int [] a = { 2 , 3 , 5 };
int size = a.length;
System.out.println(ugly(a, size, 10 ));
}
}
|
Python3
def ugly(a, size, n):
if (n < = 0 ):
return - 1
if (n = = 1 ):
return 1
pq = []
for i in range (size):
pq.append(a[i])
count = 1
no = 0
pq = sorted (pq)
while (count < n):
no = pq[ 0 ]
del pq[ 0 ]
if (no ! = pq[ 0 ]):
count + = 1
for i in range (size):
pq.append(no * a[i])
pq = sorted (pq)
return no
if __name__ = = '__main__' :
a = [ 2 , 3 , 5 ]
size = len (a)
print (ugly(a, size, 1000 ))
|
C#
using System;
using System.Collections.Generic;
class Program {
static int Ugly( int [] a, int size, int n) {
if (n <= 0) {
return -1;
}
if (n == 1) {
return 1;
}
List< int > pq = new List< int >();
for ( int i = 0; i < size; i++) {
pq.Add(a[i]);
}
int count = 1;
int no = 0;
pq.Sort();
while (count < n) {
no = pq[0];
pq.RemoveAt(0);
if (no != pq[0]) {
count++;
for ( int i = 0; i < size; i++) {
pq.Add(no * a[i]);
}
}
pq.Sort();
}
return no;
}
static void Main() {
int [] a = {2, 3, 5};
int size = a.Length;
Console.WriteLine(Ugly(a, size, 1000));
}
}
|
Javascript
<script>
function ugly(a,size,n)
{
if (n <= 0)
return -1;
if (n == 1)
return 1;
let pq=[];;
for (let i = 0; i < size; i++){
pq.push(a[i]);
}
let count = 1, no;
pq.sort( function (a,b){ return a-b;}) ;
while (count < n){
no = pq.shift();
if (no != pq[0])
{
count++;
for (let i = 0; i < size; i++){
pq.push(no * a[i]);
}
}
pq.sort( function (a,b){ return a-b;}) ;
}
return no;
}
let a=[2, 3,5];
let size = a.length;
document.write(ugly(a, size, 1000));
</script>
|
Time Complexity: O(n*size*logn)
Auxiliary Space: O(n)
Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above. If you like GeeksforGeeks and would like to contribute, you can also write an article using write.geeksforgeeks.org or mail your article to review-team@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.