Sword Pointer Offer 49. Ugly Number && 264. Ugly Number II ●●

264. Ox number II

describe

A number containing only prime factors 2, 3, and 5 is called an ugly number (Ugly Number).

Usually 1 is the first ugly number, find the nth ugly number in ascending order.

example

Input: n = 10
Output: 12
Explanation: [1, 2, 3, 4, 5, 6, 8, 9, 10, 12] is a sequence consisting of the first 10 ugly numbers.

answer

1. Small top pile

To get the nth ugly number from small to large, you can use the minimum heap to achieve.

Initially the heap is empty. First add the smallest ugly number 1 to the heap.

Take out the top element x of the heap each time, which is the smallest ugly number in the heap . Since 2x, 3x, 5x are also ugly numbers, add 2x, 3x, 5x to the heap.

The above approach will lead to duplicate elements in the heap. In order to avoid duplicate elements, you can use the hash set to deduplicate to avoid adding the same element to the heap multiple times.

In the case of excluding duplicate elements, the element taken out from the minimum heap for the nth time is the nth ugly number.

  • Time complexity: O ( n log ⁡ n ) O(n \log n)O ( nlogn ) . Obtaining the nth ugly number requires n cycles, and each cycle needs totake out1 element from the minimum heap andaddat most 3 elements to the minimum heap, so the time complexity of each cycle isO ( log ⁡ ( 3 n ) + 3 log ⁡ ( 3 n ) ) O(\log (3n) + 3 \log (3n))O(log(3n)+3log ( 3 n )) , the total time complexity isO ( n log ⁡ n ) O(n \log n )O ( nlogn)
  • Space Complexity: O ( n ) O(n)O ( n ) . The space complexity mainly depends on the size of the minimum heap and the hash set, and the size of the minimum heap and the hash set will not exceed 3n.
class Solution {
    
    
public:
    int nthUglyNumber(int n) {
    
    
        vector<int> factors = {
    
    2, 3, 5};		// 因子
        unordered_set<long> hash;				// 哈希
        priority_queue<long, vector<long>, greater<long>> heap;	// 小顶堆
        hash.insert(1L);
        heap.push(1L);
        int uglyn = 1;							
        for(int i = 1; i <= n; ++i){
    
    
            long top = heap.top();
            heap.pop();
            uglyn = (int)top;					// 第n个丑数
            for(int factor : factors){
    
    			// 堆中最小的丑数 * 因子2/3/5
                long next = top * factor;
                if(hash.count(next) == 0){
    
    
                    hash.insert(next);
                    heap.push(next);
                }
            }
        }
        return uglyn;
    }
};

2. Dynamic programming

Method 1 uses the minimum heap, which will store more ugly numbers in advance, and the process of maintaining the minimum heap also leads to high time complexity. Optimization
can be done using dynamic programming .

Define the array uglys, where uglys[i-1]represents the i-th ugly number.
uglys[0] = 1;

How to get the rest of the ugly numbers? Each ugly number has a chance to be multiplied by 2/3/5, define three pointers p2, p3, p5, which means that the next ugly number is the minimum value
obtained by multiplying the ugly number pointed by the three pointers by the corresponding prime factor value . Initially, the values ​​of the three pointers are all 0, and the corresponding pointers will be +1 in each round.

uglys[i] = min(min(num2, num3), num5);
When performing pointer judgment and moving operations, compare the results obtained by each pointer to remove repeated operations , such as 5*2 and 2*5, then both p2 and p5 are moved to the right.

  • Time complexity: O(n). It is necessary to calculate n elements in the array, and the calculation of each element can be completed in O(1) time.
  • Space complexity: O(n)
class Solution {
    
    
public:
    int nthUglyNumber(int n) {
    
    
        vector<int> uglys(n, 1);
        int p2 = 0, p3 = 0, p5 = 0;
        for(int i = 1; i < n; ++i){
    
    
            int num2 = uglys[p2]*2, num3 = uglys[p3]*3, num5 = uglys[p5]*5;
            uglys[i] = min(min(num2, num3), num5);
            if(uglys[i] == num2) ++p2;
            if(uglys[i] == num3) ++p3;
            if(uglys[i] == num5) ++p5;      // 不用else,去重,2*5 跟 5*2的情况,p2与p5++
        }
        return uglys[n-1];
    }
};

Guess you like

Origin blog.csdn.net/qq_19887221/article/details/126689247