Trilogy company pen questions:
If n is an even number, divide it by 2. If n is an odd number, add 1 or minus 1. Ask how to change a given n to 1 in the least steps.
Example: n = 11: ① + n-> 12 ② n/2-> 6 ③ n/2-> 3 ④ -- n-> 2 ⑤ n/2-> 1 requires 5 steps.
The simplest method is to use DP. Set f (n) as the minimum step. The following definitions are available:
If n is an even number, f (n) = f (n/2) + 1;
If n is an odd number, f (n) = min (f (n-1), f (n + 1) + 1
= Min (f (n-1)/2), f (n + 1)/2) + 2
Or:
F (2 * k) = f (k) + 1
F (2 * k + 1) = min (f (k), f (k + 1) + 2
Using the recursive formula above, we can calculate the number from 1 to n directly, and use an array to save the minimum steps for the number of n/2 + 1 before, however, the time and space complexity are both O (n). In fact, using the recursive formula above, the time complexity can be 0 (lg n ). Observe the recurrence formula above and we can find that to calculate n, As long as n/2 and n/2 + 1 are calculated, if 59 is to be calculated, as long as the calculation is:
59->.
The Code is as follows:
Int num2one_dp (unsigned n)
{
Unsigned tmp = n, flag = 1, ret = 0, next = 1;
While (tmp> = 1) flag <= 1;
While (flag> = 1 ){
If (n & flag ){
If (ret> next) ret = next;
Ret + = 2;
++ Next;
} Else {
If (next> ret) next = ret;
Next + = 2;
+ + Ret;
}
}
Return ret;
}
The above O (lg n) solution first processes 0 and 1 at the top of n, and the following O (lg n) solution law is exactly the opposite, first process the 0 and 1 low positions of n.
Convert n (n> 1) to binary representation
(The following "Add 1" and "subtract 1" operations refer to operations performed on odd numbers, including the number of operations performed on even numbers .)
(1) If n is composed of only 1 consecutive m (n = 2 ^ s-1, m> = 2 ),
① "Add 1" Operation: m + 1 operation required
② "Minus 1" Operation: requires 2 m-1) Operations
Obviously, only when m = 2 (that is, n = 3), the number of operations used for "minus 1" is less than "plus 1.
(2) If n can be expressed as: x10m1k (m> = 1, k> = 1)
(X can be an empty string or any 01 sequence. 0 m indicates 0 consecutive m and 1 k indicates k consecutive 1 s)
① "Plus 1" Operation: k + 1 operation to get the x10m-11 if, then use "minus 1" Operation (note, this is not necessarily the optimal solution ), x10m-1 is available for a total of k + 3 operations.
② "Minus 1" Operation: 2 * k + 1 operation to get the x10m-1
Obviously, when k = 1, the number of operations for "minus 1" may be less than that for "adding 1.
It can be proved that the number of operations used for x10m1, "minus 1" is certainly not more than "plus 1.
(When k = 1, for x10m1, assume that the "Add 1" operation first takes less steps. After the "Add 1" operation, before converting x10m1 to x11, if you use the "minus 1" operation, you can directly perform the "minus 1" operation on x10m1, with fewer steps, therefore, "add 1" is used later.
For x10m1 (which can be expressed as y01t0m1, and y can be empty strings ),
After the "Add 1" operation is 2 * m + t + 2 times, the y1 is obtained.
After the "minus 1" Operation m + 2 times, y01t is obtained.
(After "Add 1 operation", m + t + 3 can also get y1)
For m> = 1, there is always m + t + 3 <= 2 * m + t + 2, so for x10m1
The "minus 1" operation ensures the optimal solution .)
(3) In short, the "minus 1" operation is used only when the minimum two bits of n = 3 or n binary are 01.
Code:
Int num2one (unsigned n)
{
If (n = 0) return-1;
Int count = 0;
While (1 ){
While (n & 1) = 0) {n> = 1u; ++ count ;}
If (n <= 3 ){
// When n can only be 1 or 3 and n is 3, two steps are required.
Count + = n-1;
Break;
}
If (n & 3) = 1) -- n;
Else ++ n;
++ Count;
}
Return count;
}