553. Optimal Division


Given a list of positive integers, the adjacent integers will perform the float division. For example, [2,3,4] -> 2 / 3 / 4.

However, you can add any number of parenthesis at any position to change the priority of operations. You should find out how to add parenthesis to get the maximum result, and return the corresponding expression in string format. Your expression should NOT contain redundant parenthesis.

Example:

Input: [1000,100,10,2]
Output: "1000/(100/10/2)"
Explanation:
1000/(100/10/2) = 1000/((100/10)/2) = 200
However, the bold parenthesis in "1000/((100/10)/2)" are redundant, 
since they don't influence the operation priority. So you should return "1000/(100/10/2)". Other cases: 1000/(100/10)/2 = 50 1000/(100/(10/2)) = 50 1000/100/10/2 = 0.5 1000/100/(10/2) = 2

Note:

  1. The length of the input array is [1, 10].
  2. Elements in the given array will be in range [2, 1000].
  3. There is only one optimal division for each test case.


Solution


Approach #1 Brute Force [Accepted]

Algorithm

Brute force of this problem is to divide the list into two parts and and call function for these two parts. We will iterate from to so that and .

and parts return their maximum and minimum value and corresponding strings.

Minimum value can be found by dividing minimum of left by maximum of right i.e. .

Similarly,Maximum value can be found by dividing maximum of left value by minimum of right value. i.e. .

Now, how to add parenthesis? As associativity of division operator is from left to right i.e. by default left most divide should be done first, we need not have to add paranthesis to the left part, but we must add parenthesis to the right part.

eg- "2/(3/4)" will be formed as leftPart+"/"+"("+rightPart+")", assuming leftPart is "2" and rightPart is"3/4".

One more point, we also don't require parenthesis to right part when it contains single digit.

eg- "2/3", here left part is "2" and right part is "3" (contains single digit) . 2/(3) is not valid.

Complexity Analysis

  • Time complexity : . Number of permutations of expression after applying brackets will be in where is the number of items in the list.

  • Space complexity: . Depth of recursion tree will be and each node contains string of maximum length .


Approach #2 Using Memorization [Accepted]

Algorithm

In the above approach we called optimal function recursively for ever and . We can notice that there are many redundant calls in the above approach, we can reduce these calls by using memorization to store the result of different function calls. Here, array is used for this purpose.

Complexity Analysis

  • Time complexity : . array of size is filled and filling of each cell of the array takes time.

  • Space complexity : . array of size where each cell of array contains string of length .


Approach #3 Using some Math [Accepted]

Algorithm

Using some simple math we can find the easy solution of this problem. Consider the input in the form of [a,b,c,d], now we have to set priority of operations to maximize a/b/c/d. We know that to maximize fraction , (denominator) should be minimized. So, to maximize we have to first minimize b/c/d. Now our objective turns to minimize the expression b/c/d.

There are two possible combinations of this expression, b/(c/d) and (b/c)/d.

b/(c/d)        (b/c)/d = b/c/d
(b*d)/c        b/(d*c)
d/c            1/(d*c)

Obviously, for .

You can see that second combination will always be less than first one for numbers greater than . So, the answer will be a/(b/c/d). Similarly for expression like a/b/c/d/e/f... answer will be a/(b/c/d/e/f...).

Complexity Analysis

  • Time complexity : . Single loop to traverse array.

  • Space complexity : . variable is used to store the result.


Analysis written by: @vinod23