|
| 1 | +# Ugly Numbers using Dynamic Programming |
| 2 | +Language used : **Python 3** |
| 3 | + |
| 4 | +## 🎯 Aim |
| 5 | +The aim of this script is to find out the n'th ugly number using Dynamic Programming. |
| 6 | + |
| 7 | +## 👉 Purpose |
| 8 | +The main purpose of this script is to show the implementation of Dynamic programming on finding out the n'th ugly number. |
| 9 | + |
| 10 | +## 📄 Description |
| 11 | +Ugly numbers are numbers whose only prime factors are 2, 3 or 5. The sequence 1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, … shows the first 11 ugly numbers. By convention, 1 is included. |
| 12 | +**Given a number n, the task is to find n’th Ugly number.** |
| 13 | + |
| 14 | +**Examples:** |
| 15 | +``` |
| 16 | +Input : n = 7 |
| 17 | +Output : 8 |
| 18 | +
|
| 19 | +Input : n = 10 |
| 20 | +Output : 12 |
| 21 | +
|
| 22 | +Input : n = 15 |
| 23 | +Output : 24 |
| 24 | +
|
| 25 | +Input : n = 150 |
| 26 | +Output : 5832 |
| 27 | +``` |
| 28 | + |
| 29 | +## 📈 Workflow of the script |
| 30 | +- `getNthUglyNo` - The main function of the script to find out the Ugly number using Dynamic Approach. |
| 31 | +- `main` - This is the driver code for this code/script. |
| 32 | + |
| 33 | +## 📃 Explanation |
| 34 | +Here is a time efficient solution with O(n) extra space. The ugly-number sequence is 1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, … |
| 35 | + because every number can only be divided by 2, 3, 5, one way to look at the sequence is to split the sequence to three groups as below: |
| 36 | + (1) 1×2, 2×2, 3×2, 4×2, 5×2, … |
| 37 | + (2) 1×3, 2×3, 3×3, 4×3, 5×3, … |
| 38 | + (3) 1×5, 2×5, 3×5, 4×5, 5×5, … |
| 39 | + We can find that every subsequence is the ugly-sequence itself (1, 2, 3, 4, 5, …) multiply 2, 3, 5. Then we use similar merge method as merge sort, to get every ugly number from the three subsequences. Every step we choose the smallest one, and move one step after. |
| 40 | +``` |
| 41 | +1. Declare an array for ugly numbers: ugly[n] |
| 42 | +2. Initialize first ugly no: ugly[0] = 1 |
| 43 | +3. Initialize three array index variables i2, i3, i5 to point to |
| 44 | + 1st element of the ugly array: |
| 45 | + i2 = i3 = i5 =0; |
| 46 | +4. Initialize 3 choices for the next ugly no: |
| 47 | + next_mulitple_of_2 = ugly[i2]*2; |
| 48 | + next_mulitple_of_3 = ugly[i3]*3 |
| 49 | + next_mulitple_of_5 = ugly[i5]*5; |
| 50 | +5. Now go in a loop to fill all ugly numbers till 150: |
| 51 | +For (i = 1; i < 150; i++ ) |
| 52 | +{ |
| 53 | + /* These small steps are not optimized for good |
| 54 | + readability. Will optimize them in C program */ |
| 55 | + next_ugly_no = Min(next_mulitple_of_2, |
| 56 | + next_mulitple_of_3, |
| 57 | + next_mulitple_of_5); |
| 58 | +
|
| 59 | + ugly[i] = next_ugly_no |
| 60 | +
|
| 61 | + if (next_ugly_no == next_mulitple_of_2) |
| 62 | + { |
| 63 | + i2 = i2 + 1; |
| 64 | + next_mulitple_of_2 = ugly[i2]*2; |
| 65 | + } |
| 66 | + if (next_ugly_no == next_mulitple_of_3) |
| 67 | + { |
| 68 | + i3 = i3 + 1; |
| 69 | + next_mulitple_of_3 = ugly[i3]*3; |
| 70 | + } |
| 71 | + if (next_ugly_no == next_mulitple_of_5) |
| 72 | + { |
| 73 | + i5 = i5 + 1; |
| 74 | + next_mulitple_of_5 = ugly[i5]*5; |
| 75 | + } |
| 76 | + |
| 77 | +}/* end of for loop */ |
| 78 | +
|
| 79 | +6.return next_ugly_no |
| 80 | +``` |
| 81 | + |
| 82 | +## 🧮 Algorithm |
| 83 | +Let us see how it works, |
| 84 | +``` |
| 85 | +initialize |
| 86 | + ugly[] = | 1 | |
| 87 | + i2 = i3 = i5 = 0; |
| 88 | +
|
| 89 | +First iteration |
| 90 | + ugly[1] = Min(ugly[i2]*2, ugly[i3]*3, ugly[i5]*5) |
| 91 | + = Min(2, 3, 5) |
| 92 | + = 2 |
| 93 | + ugly[] = | 1 | 2 | |
| 94 | + i2 = 1, i3 = i5 = 0 (i2 got incremented ) |
| 95 | +
|
| 96 | +Second iteration |
| 97 | + ugly[2] = Min(ugly[i2]*2, ugly[i3]*3, ugly[i5]*5) |
| 98 | + = Min(4, 3, 5) |
| 99 | + = 3 |
| 100 | + ugly[] = | 1 | 2 | 3 | |
| 101 | + i2 = 1, i3 = 1, i5 = 0 (i3 got incremented ) |
| 102 | +
|
| 103 | +Third iteration |
| 104 | + ugly[3] = Min(ugly[i2]*2, ugly[i3]*3, ugly[i5]*5) |
| 105 | + = Min(4, 6, 5) |
| 106 | + = 4 |
| 107 | + ugly[] = | 1 | 2 | 3 | 4 | |
| 108 | + i2 = 2, i3 = 1, i5 = 0 (i2 got incremented ) |
| 109 | +
|
| 110 | +Fourth iteration |
| 111 | + ugly[4] = Min(ugly[i2]*2, ugly[i3]*3, ugly[i5]*5) |
| 112 | + = Min(6, 6, 5) |
| 113 | + = 5 |
| 114 | + ugly[] = | 1 | 2 | 3 | 4 | 5 | |
| 115 | + i2 = 2, i3 = 1, i5 = 1 (i5 got incremented ) |
| 116 | +
|
| 117 | +Fifth iteration |
| 118 | + ugly[4] = Min(ugly[i2]*2, ugly[i3]*3, ugly[i5]*5) |
| 119 | + = Min(6, 6, 10) |
| 120 | + = 6 |
| 121 | + ugly[] = | 1 | 2 | 3 | 4 | 5 | 6 | |
| 122 | + i2 = 3, i3 = 2, i5 = 1 (i2 and i3 got incremented ) |
| 123 | +
|
| 124 | +Will continue same way till I < 150 |
| 125 | +``` |
| 126 | + |
| 127 | +## 💻 Input and Output |
| 128 | +- **Test Case 1 :** |
| 129 | + |
| 130 | + |
| 131 | + |
| 132 | +- **Test Case 2 :** |
| 133 | + |
| 134 | + |
| 135 | + |
| 136 | +- **Test Case 3 :** |
| 137 | + |
| 138 | + |
| 139 | + |
| 140 | +- **Test Case 4 :** |
| 141 | + |
| 142 | + |
| 143 | + |
| 144 | +## ⏰ Time and Space complexity |
| 145 | +- **Time Complexity:** `O(n)`. |
| 146 | +- **Space Complexity:** `O(n)`. |
| 147 | + |
| 148 | +--------------------------------------------------------------- |
| 149 | +## 🖋️ Author |
| 150 | +**Code contributed by, _Abhishek Sharma_, 2021 [@abhisheks008](github.com/abhisheks008)** |
| 151 | + |
| 152 | +[](https://www.python.org/) |
0 commit comments