Skip to content

Latest commit

 

History

History
216 lines (154 loc) · 8.06 KB

File metadata and controls

216 lines (154 loc) · 8.06 KB

Analysis

For simplicity, let us use L to represent the number of digits in N, note the scale of L is actually O(log10N). And let us use {aL−1,aL−2,…,a1,a0} to represent the digits of N, where aL−1 is the most significant digit and a0 is the least significant digit (0 ≤ ai ≤ 9 for all i < L−1, and 1 ≤ aL−1 ≤ 9). We can read N as a string, where the characters in the string {s[0],s[1],…,s[L−2],s[L−1]} represent {aL−1,aL−2,…,a1,a 0}. Or, we can read N as an integer, whose value equals aL−1 × 10L−1 + aL−2 × 10L−2 + ⋯ + a1 × 10 + a0. Inserting a new digit d in the k−th position in N means inserting it after the first Lk digits (on the left side) and before the last k digits (on the right side) of N. If N is string type, then the new number can be built by slicing and concatenating the string as s[0…Lk] + string(d) + s[LkL] in linear time, where s[ij] means characters of string s from index i to index j. On the other hand, if N is integer type, then the new number can be calculated as (NN%10k) × 10 + d × 10k + (N%10k) in constant time.

Test Set 1

Since N ≤ 105, the number of digits of N is at most 6, which means there are at most 7 positions to insert a new digit. As for the new digit, there are at most 10 options (09), therefore the total number of results is at most 70. We can enumerate all these 70 results, eliminate those ones which are not multiples of 9 or have leading zeros, then find the smallest one from them.

In this solution, there are O(L) positions to insert a new digit, and a constant number of choices for the new digit (09). If N is read as an integer, then we need constant time to insert a new digit, decide if the inserted result is a multiple of 9 and compare the candidates, so the time complexity of this solution is O(L). If N is read as a string, then every operation such as the insertion of a new digit or value comparison among candidates will take O(L) time, so the time complexity will be O(L2).

Test Set 2

Now that N is at most 10123456, we cannot read N as 32-bit/64-bit integer [sic]. Instead, we should read N as string [sic] where each character represents a digit of N. Since L is at most 123456 + 1, the brute force enumeration method with time complexity O(L2) is unacceptable. We need a more efficient algorithm.

First, let us decide which digit to insert. In fact, a number is a multiple of 9 if and only if the sum of its all digits is a multiple of 9. Therefore, we can add up all the L digits of the given N, and use 9 − (sum mod 9) to get the new digit we want. Wherever we insert it, the sum of all digits of the new number and the new number itself will be a multiple of 9. Note that when sum mod 9 = 0, adding either a new 0 or a new 9 can make the result be a multiple of 9, but 0 is always more preferable than 9 because we are looking for the smallest answer.

Secondly, let us decide where to insert the new digit. Let us use d to represent the new digit we are going to insert. We can start from the most significant digit aL−1, then aL−2, and then use this order to visit all the digits in N, to find the first digit in N that is larger than d. Then we should insert d right before this digit. In other words, say ak is the first digit in N that is larger than d (i.e. aid for all k + 1 ≤ iL − 1), then the new number we are going to make is {aL−1,aL−2,…,ak+1,d,ak,…,a0}, whose value equals to Ng = aL−1 × 10L + aL−2 × 10L−1 + ⋯ + ak+1 × 10k+2 + d × 10k+1 + ak × 10k + ⋯ + a0.

Is this always the best choice? Yes, let us prove it. If we insert d to a more significant position, i.e. between aq+1 and aq where q > k, then the new number we are going to make is {aL−1,aL−2,…,aq+1,d,aq,…,ak,…,a0} with value No = aL−1 × 10L + aL−2 × 10L−1 + ⋯ + aq+1 × 10q+2 + d × 10q+1 + aq × 10q + ⋯ ak × 10k + ⋯ + a0. The difference between this solution and the solution we claimed is NoNg = d × 10q+1 − 9 × (aq × 10q + aq-1 × 10q-1 + ⋯ + ak+2 × 10k+2 + ak+1 × 10k+1) − d × 10k+1. Since we have that aq is always no greater than d, we can make sure that 9 × (aq × 10q + aq-1 × 10q-1 + ⋯ + ak+2 × 10k+2 + ak+1 × 10k+1) + d × 10k+1 is always no greater than d × 10q+1. Therefore, no matter what other position q we choose to insert d, the result is always no less than inserting at k.

On the other hand, if we insert d to a less significant position, i.e. between ap+1 and ap where p < k, then the new number we are going to make is {aL−1,aL−2,…,ak,…,ap+1,d,ap,…,a0} with value No = aL−1 × 10L + aL−2 × 10L−1 + ⋯ + ak × 10k+1 + ⋯ + ap+1 × 10p+2 + d × 10p+1 + ap × 10p + ⋯ + a0. The difference between this solution and the solution we claimed is NoNg = −d × 10k+1 + 9 × (ak × 10k + ⋯ + ap+1 × 10p+1) + d × 10p+1. Since we have that ak > d, we can make sure that 9 × (ak × 10k + ⋯ + ap+1 × 10p+1) + d × 10p+1 is always greater than d × 10k+1. Therefore, no matter what other position p we choose to insert d, the result is always greater than inserting at k.

Note that there are some edge cases. For example, all digits in N are less than d. In this case, we should append d to the end of N. And if d is 0, we will find that the first digit in N that is larger than d is the leading digit. Be careful that we should not put d before it because the result cannot have leading zeros. In this case, we should put 0 right after the leading digit of N to get the smallest result.

The time complexity for finding out which d to insert is O(L) because we need to add up all digits of N to get the remainder of N divided by 9. Then to find where to insert d, we also need O(L) time to visit all the digits to find the first digit that is larger than d (or find out all the digits are no larger than d). Therefore, the total time complexity of this solution is O(L + L) = O(L).

Test Data