964. Least Operators to Express Number

Average Rating: 3.20 (15 votes)

Dec. 23, 2018 | 4.6K views

Given a single positive integer x, we will write an expression of the form x (op1) x (op2) x (op3) x ... where each operator op1, op2, etc. is either addition, subtraction, multiplication, or division (+, -, *, or /). For example, with x = 3, we might write 3 * 3 / 3 + 3 - 3 which is a value of 3.

When writing such an expression, we adhere to the following conventions:

The division operator (/) returns rational numbers.

There are no parentheses placed anywhere.

We use the usual order of operations: multiplication and division happens before addition and subtraction.

It's not allowed to use the unary negation operator (-). For example, "x - x" is a valid expression as it only uses subtraction, but "-x + x" is not because it uses negation.

We would like to write an expression with the least number of operators such that the expression equals the given target. Return the least number of operators used.

Solution

Approach 1: Dynamic Programming

Intuition

First, we notice that we can consider blocks of multiplication and division separately. Each block is a power of x: either x / x, x, x * x, x * x * x, x * x * x * x and so on. (There is no point to write expressions like x * x / x because it uses strictly more operators.)

Let's think of the cost of a block as all the operators needed to express it, including the addition or subtraction operator in front of it. For example, we can think of x * x + x + x / x as (+ x * x) (+ x) (+ x / x) for a cost of 2 + 1 + 2, minus 1 for the leading + (so the total cost is 4).

We can write the cost of writing a block that has value : it is , except when it is 2. We want the sum of the costs of all blocks minus 1.

Now, we have the reduced problem: we have the costs of writing all or , and we want to find the least cost to express the target.

Notice that modulo , the only blocks that change the expression are . Let . So we must either subtract
's, or add
's. This will form a new "remaining" target, , that is divisible by .

Then, modulo , the only blocks that change the expression are and . However, since the new target is divisible by , there is no point to use , as we would have to use at least of them to do the same work as one use of , which is a strictly higher cost.

Again, in a similar way, we have , and we must either subtract
's, or add
's. This will form a new remaining target , and so on.

As a concrete example, say x = 5, target = 123. We either add 2 or subtract 3. This leaves us with a target of 120 or 125. If the target is 120, we can either add 5 or subtract 20, leaving us with a target of 100 or 125. If the target is 100, we can either add 25 or subtract 100, leaving us with a target of 125 or 0. If the target is 125, we subtract 125.

Algorithm

Let's calculate dp(i, target) using a top down dp. Here, i will be the exponent of the block being considered, and target will be the remaining target, already divided by .

From here, the recursion is straightforward: , and we either subtract blocks or add of them. The base cases are easily deduced - see the code for more details.

Complexity Analysis

Time Complexity: . We can prove that we only visit up to two states for each base-x digit of .