Topic description
Call numbers that contain only factors 2, 3, and 5 Ugly Numbers;
For example, 6 and 8 are ugly numbers, but 14 is not because it contains the factor 7;
Traditionally we treat 1 as the first ugly number. Find the Nth ugly number in ascending order;
Problem solving ideas
Let's talk about a violent solution first to provide ideas;
If p is an ugly number, then p=2^x * 3^y * 5^z, then you can get different ugly numbers by assigning different values to x, y, and z;
If you want to find the ugly numbers sequentially, you need to know the following characteristics: For any ugly number p: 2*p, 3*p, 5*p are all ugly numbers, and 2*p<3*p<5*p; If p<q, then 2*p<2*q, 3*p<3*q, 5*p<5*q;
Since 1 is the smallest ugly number, starting from 1, compare 2*1, 3*1, 5*1, and the smallest one is the next ugly number of 1, which is 2*1;
At this time, there is one more ugly number '2', and there are three more ugly numbers that can be compared, 2*2, 3*2, 5*2,
At this time, add the ugly number generated by '1' and the ugly number generated by '2', that is, (3*1, 5*1, 2*2, 3*2, 5*2) for comparison, and find out the smallest;
If this cycle continues, you will find that each time an ugly number is selected, the ugly number will generate 3 new ugly numbers for comparison;
Next, say an O(n) algorithm;
Since there is p<q, then 2*p<2*q, then "I" is not selected in front of the number smaller than you, and the new ugly number you generate later must be larger than "I", then you multiply by 2The generated ugly number must be bigger than the one I multiply by 2, then you will have the chance to choose it after I choose it.
In fact, we only compare 3 numbers each time: the smallest number for multiplying by 2, the smallest number for multiplying by 3, and the smallest number for multiplying by 5. That is to compare (2*x, 3*y, 5*z), x>=y>=z,
Focus on the role of p in the following code: int p[] = new int[] { 0, 0, 0 }; p[0] represents the minimum [position] in the array a for multiplying the comparison number by 2.
final int d[] = {2, 3, 5}; private int finMin(int num2, int num3, int num5) { int min = Math.min(num2, Math.min(num3, num5)); return min == num2? 0: min == num3? 1: 2; } public int GetUglyNumber_Solution(int index) { if (index == 0){ return 0; } int a[] = new int[index]; a[0] = 1; //1 is the first ugly number int p[] = new int[]{0, 0, 0}; int num[] = new int[]{2, 3, 5}; int cur = 1; while (cur < index) { int m = finMin(num[0], num[1], num[2]); if (a[cur - 1] < num[m]) a[cur++] = num[m]; p[m] += 1; num[m] = a[p[m]] * d[m]; } return a[index - 1]; }