Ugly Number III - Complete Solution Guide
Ugly Number III is LeetCode problem 1201, a Medium level challenge. This complete guide provides step-by-step explanations, multiple solution approaches, and optimized code in python3, java, cpp, c.
Problem Statement
An ugly number is a positive integer that is divisible by a , b , or c . Given four integers n , a , b , and c , return the n th ugly number . Example 1: Input: n = 3, a = 2, b = 3, c = 5 Output: 4 Explanation: The ugly numbers are 2, 3, 4, 5, 6, 8, 9, 10... The 3 rd is 4. Example 2: Input: n = 4, a = 2, b = 3, c = 4 Output: 6 Explanation: The ugly numbers are 2, 3, 4, 6, 8, 9, 10, 12... The 4 th is 6. Example 3: Input: n = 5, a = 2, b = 11, c = 13 Output: 10 Explanation: The ugly numbers are 2,
Detailed Explanation
The problem asks us to find the nth 'ugly number'. An ugly number is defined as a positive integer that is divisible by at least one of the given integers a, b, or c. The input consists of four integers: n (the desired ugly number's rank), a, b, and c (the divisors). The output should be the nth ugly number.
Solution Approach
The solution employs binary search to find the nth ugly number. For a given mid-point value, it determines how many numbers less than or equal to mid are divisible by a, b, or c. This count is obtained using the inclusion-exclusion principle. If the count is less than n, we search in the higher half; otherwise, we search in the lower half. The binary search continues until low and high converge on the nth ugly number.
Step-by-Step Algorithm
- Step 1: Define a function gcd(x, y) to calculate the greatest common divisor of two numbers x and y using the Euclidean algorithm.
- Step 2: Define a function lcm(x, y) to calculate the least common multiple of two numbers x and y using the formula lcm(x, y) = (x * y) / gcd(x, y).
- Step 3: Calculate lcm(a, b), lcm(a, c), lcm(b, c), and lcm(a, lcm(b,c)). These values are used in the inclusion-exclusion principle.
- Step 4: Initialize low to 1 and high to 2 * 10^9 (based on the problem's constraint).
- Step 5: Perform binary search: While low < high, calculate mid = low + (high - low) // 2.
- Step 6: Calculate the count of ugly numbers less than or equal to mid using the inclusion-exclusion principle: count = (mid // a) + (mid // b) + (mid // c) - (mid // lcm_ab) - (mid // lcm_ac) - (mid // lcm_bc) + (mid // lcm_abc).
- Step 7: If count < n, it means the nth ugly number is greater than mid, so update low = mid + 1. Otherwise, the nth ugly number is less than or equal to mid, so update high = mid.
- Step 8: After the loop terminates (low == high), low (or high) will be the nth ugly number. Return low.
Key Insights
- Insight 1: The key idea is to use binary search. Since we're looking for the nth ugly number within a certain range (1 to 2 * 10^9), we can efficiently narrow down the search space.
- Insight 2: The principle of inclusion-exclusion is crucial for counting the number of ugly numbers less than or equal to a given number 'mid'. We need to account for numbers divisible by a, b, and c individually, then subtract overlaps (divisible by lcm(a,b), lcm(a,c), lcm(b,c)), and finally add back the overlap of overlaps (divisible by lcm(a,b,c)).
- Insight 3: The least common multiple (LCM) calculations can result in large numbers, so using long data types in Java/C++ and proper integer division in Python is important to avoid overflow.
Complexity Analysis
Time Complexity: O(log(n))
Space Complexity: O(1)
Topics
This problem involves: Math, Binary Search, Combinatorics, Number Theory.
Companies
Asked at: American Express.