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


    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 题目汇总

  • 相关阅读:
    VC 常见问题百问
    python windows 环境变量
    Check server headers and verify HTTP Status Codes
    Where are the AES 256bit cipher suites? Please someone help
    outlook 如何预订会议和会议室
    安装Axis2的eclipse插件后,未出现界面
    windows 环境变量
    python 时间日期处理汇集
    openldap学习笔记(使用openldap2.3.32)
    set p4 environment in windows
  • 原文地址:https://www.cnblogs.com/lightwindy/p/9758211.html
Copyright © 2020-2023  润新知