Open In App

Generate a sequence such that float division of array elements is maximized

Improve
Improve
Like Article
Like
Save
Share
Report

Given an array arr[] consisting of N integers, the task is to find the expression by using parenthesis ‘(‘ and ‘)’ and division operator ‘/’ to maximize the value of the expression of subsequent float division of array elements.

Examples:

Input: arr[] = {1000, 100, 10, 2}
Output: “1000/(100/10/2)”
Explanation:
The value of the expression 1000/(100/10/2) can be calculated as 1000/((100/10)/2) = 200.

Input: arr[] = {2, 3, 4}
Output: “2/(3/4)”

Brute Force Approach:

To solve the problem of finding the maximum and minimum value of an expression with numbers and division operators, we can divide the array into two parts, left and right. We can iterate through the array, assigning i as the dividing point where the left part is from the start to i, and the right part is from i+1 to the end.

The left and right parts can then be processed recursively, returning their maximum and minimum values along with their corresponding strings. To find the minimum value of the whole expression, we divide the minimum value of the left part by the maximum value of the right part. Similarly, to find the maximum value of the expression, we divide the maximum value of the left part by the minimum value of the right part.

To add parentheses to the expression, we need to consider the associativity of the division operator. As the associativity is from left to right, we do not need to add parentheses to the left part. However, we must add parentheses to the right part. For example, “2/(3/4)” can be formed as leftPart + “/” + “(” + rightPart + “)”, where leftPart is “2” and rightPart is “3/4”.

However, if the right part contains a single digit, we do not need to add parentheses to it. For example, in “2/3”, the left part is “2” and the right part is “3” (which contains a single digit). Therefore, we do not need to add parentheses to it, and “2/3” is a valid expression.

Algorithm:

  1. Create a struct/class T that contains four fields: max_val, min_val, max_str, and min_str. max_val and min_val will be used to store the maximum and minimum values of the expression, respectively. max_str and min_str will be used to store the corresponding string expressions that give rise to the maximum and minimum values, respectively.
  2. Create a recursive function optimal that takes in the array of integers nums, the starting index start, the ending index end, and a string res. The res string will be used to build the string expressions for the maximum and minimum values. The function should return an instance of the T struct.
  3. In the optimal function, if the start index is equal to the end index, then create an instance of the T struct and set all four fields to the value of nums[start]. Return this instance.
  4. Otherwise, create an instance of the T struct and initialize min_val to FLT_MAX and max_val to FLT_MIN.
  5. Loop through the array of integers from index start to index end – 1. For each index i, call the optimal function recursively with the left subarray nums[start..i] and the right subarray nums[i+1..end]. Store the returned instances of the T struct in variables left and right.
  6. Compute the minimum value of the expression by dividing left.min_val by right.max_val. If this value is less than the current value of         min_val in the current T struct, then update min_val to this value and update min_str to be the concatenation of left.min_str, “/”, “(“,         and right.max_str, followed by “)”.
  7. Compute the maximum value of the expression by dividing left.max_val by right.min_val. If this value is greater than the current value of max_val in the current T struct, then update max_val to this value and update max_str to be the concatenation of left.max_str, “/”,        “(“, and right.min_str, followed by “)”.
  8. After looping through all possible dividing points, return the instance of the T struct that has the maximum value of the expression.
  9. Create a function optimalDivision that takes in an array of integers nums. Call the optimal function with nums, 0, nums.size() – 1, and an empty string. Return the max_str field of the returned instance of the T struct.

Below is the implementation of the approach:

C++




// C++ program for the approach
 
#include <bits/stdc++.h>
using namespace std;
 
// Structure to store the minimum and
// maximum value of an expression along
// with its string representation
struct T {
    float max_val, min_val;
    string min_str, max_str;
};
 
// Function to find the minimum and
// maximum value of an expression
T optimal(int nums[], int start, int end)
{
    T t;
 
    // If only one number is left
    if (start == end) {
        t.max_val = nums[start];
        t.min_val = nums[start];
        t.min_str = to_string(nums[start]);
        t.max_str = to_string(nums[start]);
        return t;
    }
    t.min_val = FLT_MAX;
    t.max_val = FLT_MIN;
    t.min_str = "";
    t.max_str = "";
 
    // Iterate through all possible
    // dividing points
    for (int i = start; i < end; i++) {
 
        // Find the optimal value of
        // the left part
        T left = optimal(nums, start, i);
 
        // Find the optimal value of
        // the right part
        T right = optimal(nums, i + 1, end);
 
        // Find the minimum value of
        // the expression
        if (t.min_val > left.min_val / right.max_val) {
            t.min_val = left.min_val / right.max_val;
            t.min_str = left.min_str + "/"
                        + (i + 1 != end ? "(" : "")
                        + right.max_str
                        + (i + 1 != end ? ")" : "");
        }
 
        // Find the maximum value of
        // the expression
        if (t.max_val < left.max_val / right.min_val) {
            t.max_val = left.max_val / right.min_val;
            t.max_str = left.max_str + "/"
                        + (i + 1 != end ? "(" : "")
                        + right.min_str
                        + (i + 1 != end ? ")" : "");
        }
    }
 
    // Return the value of t
    return t;
}
 
// Function to return the string representation
// of the maximum value of the expression
string optimalDivision(int nums[], int n)
{
    T t = optimal(nums, 0, n - 1);
    return t.max_str;
}
 
// Driver Code
int main()
{
 
    int nums[] = { 1000, 100, 10, 2 };
    int n = sizeof(nums) / sizeof(nums[0]);
    cout << optimalDivision(nums, n);
 
    return 0;
}


Java




// Java program for the approach
 
import java.util.*;
 
// Class to store the minimum and
// maximum value of an expression along
// with its string representation
class T {
    float max_val, min_val;
    String min_str, max_str;
}
 
// Class for the problem
class GFG {
    // Function to find the minimum and
    // maximum value of an expression
    public static T optimal(int nums[], int start, int end)
    {
        T t = new T();
 
        // If only one number is left
        if (start == end) {
            t.max_val = nums[start];
            t.min_val = nums[start];
            t.min_str = Integer.toString(nums[start]);
            t.max_str = Integer.toString(nums[start]);
            return t;
        }
        t.min_val = Float.MAX_VALUE;
        t.max_val = Float.MIN_VALUE;
        t.min_str = "";
        t.max_str = "";
 
        // Iterate through all possible
        // dividing points
        for (int i = start; i < end; i++) {
 
            // Find the optimal value of
            // the left part
            T left = optimal(nums, start, i);
 
            // Find the optimal value of
            // the right part
            T right = optimal(nums, i + 1, end);
 
            // Find the minimum value of
            // the expression
            if (t.min_val > left.min_val / right.max_val) {
                t.min_val = left.min_val / right.max_val;
                t.min_str = left.min_str + "/"
                            + (i + 1 != end ? "(" : "")
                            + right.max_str
                            + (i + 1 != end ? ")" : "");
            }
 
            // Find the maximum value of
            // the expression
            if (t.max_val < left.max_val / right.min_val) {
                t.max_val = left.max_val / right.min_val;
                t.max_str = left.max_str + "/"
                            + (i + 1 != end ? "(" : "")
                            + right.min_str
                            + (i + 1 != end ? ")" : "");
            }
        }
 
        // Return the value of t
        return t;
    }
 
    // Function to return the string representation
    // of the maximum value of the expression
    public static String optimalDivision(int nums[], int n)
    {
        T t = optimal(nums, 0, n - 1);
        return t.max_str;
    }
 
    // Driver code
    public static void main(String args[])
    {
        int nums[] = { 1000, 100, 10, 2 };
        int n = nums.length;
        System.out.println(optimalDivision(nums, n));
    }
}


Python3




# Python3 program for the above approach
 
# Class to store the minimum and
# maximum value of an expression along
# with its string representation
class T:
    def __init__(self):
        self.max_val = float('-inf')
        self.min_val = float('inf')
        self.min_str = ""
        self.max_str = ""
 
def optimal(nums, start, end):
    t = T()
 
    # If only one number is left
    if start == end:
        t.max_val = nums[start]
        t.min_val = nums[start]
        t.min_str = str(nums[start])
        t.max_str = str(nums[start])
        return t
 
    # Iterate through all possible dividing points
    for i in range(start, end):
        # Find the optimal value of the left part
        left = optimal(nums, start, i)
 
        # Find the optimal value of the right part
        right = optimal(nums, i + 1, end)
 
        # Find the minimum value of the expression
        if t.min_val > left.min_val / right.max_val:
            t.min_val = left.min_val / right.max_val
            t.min_str = left.min_str + "/"
            if i + 1 != end:
                t.min_str += "("
            t.min_str += right.max_str
            if i + 1 != end:
                t.min_str += ")"
 
        # Find the maximum value of the expression
        if t.max_val < left.max_val / right.min_val:
            t.max_val = left.max_val / right.min_val
            t.max_str = left.max_str + "/"
            if i + 1 != end:
                t.max_str += "("
            t.max_str += right.min_str
            if i + 1 != end:
                t.max_str += ")"
 
    # Return the value of t
    return t
 
def optimal_division(nums):
    n = len(nums)
    t = optimal(nums, 0, n - 1)
    return t.max_str
 
# Driver code
if __name__ == "__main__":
    nums = [1000, 100, 10, 2]
    print(optimal_division(nums))
 
#This code is contributed by aeroabrar_31


C#




using System;
 
// Class to store the minimum and
// maximum value of an expression along
// with its string representation
class T {
  public float max_val, min_val;
  public string min_str, max_str;
}
 
// Class for the problem
class GFG {
  // Function to find the minimum and
  // maximum value of an expression
  public static T Optimal(int[] nums, int start, int end)
  {
    T t = new T();
    // If only one number is left
    if (start == end) {
      t.max_val = nums[start];
      t.min_val = nums[start];
      t.min_str = nums[start].ToString();
      t.max_str = nums[start].ToString();
      return t;
    }
    t.min_val = float.MaxValue;
    t.max_val = float.MinValue;
    t.min_str = "";
    t.max_str = "";
 
    // Iterate through all possible
    // dividing points
    for (int i = start; i < end; i++) {
 
      // Find the optimal value of
      // the left part
      T left = Optimal(nums, start, i);
 
      // Find the optimal value of
      // the right part
      T right = Optimal(nums, i + 1, end);
 
      // Find the minimum value of
      // the expression
      if (t.min_val > left.min_val / right.max_val) {
        t.min_val = left.min_val / right.max_val;
        t.min_str = left.min_str + "/"
          + (i + 1 != end ? "(" : "")
          + right.max_str
          + (i + 1 != end ? ")" : "");
      }
 
      // Find the maximum value of
      // the expression
      if (t.max_val < left.max_val / right.min_val) {
        t.max_val = left.max_val / right.min_val;
        t.max_str = left.max_str + "/"
          + (i + 1 != end ? "(" : "")
          + right.min_str
          + (i + 1 != end ? ")" : "");
      }
    }
 
    // Return the value of t
    return t;
  }
 
  // Function to return the string representation
  // of the maximum value of the expression
  public static string OptimalDivision(int[] nums, int n)
  {
    T t = Optimal(nums, 0, n - 1);
    return t.max_str;
  }
 
  // Driver code
  public static void Main(string[] args)
  {
    int[] nums = { 1000, 100, 10, 2 };
    int n = nums.Length;
    Console.WriteLine(OptimalDivision(nums, n));
  }
}


Javascript




// Class to store the minimum and maximum value of an expression along
// with its string representation
class T {
    constructor() {
        this.max_val = 0;
        this.min_val = 0;
        this.min_str = '';
        this.max_str = '';
    }
}
 
// Function to find the minimum and maximum value of an expression
function optimal(nums, start, end) {
    const t = new T();
 
    // If only one number is left
    if (start === end) {
        t.max_val = nums[start];
        t.min_val = nums[start];
        t.min_str = nums[start].toString();
        t.max_str = nums[start].toString();
        return t;
    }
    t.min_val = Number.MAX_VALUE;
    t.max_val = Number.MIN_VALUE;
    t.min_str = '';
    t.max_str = '';
 
    // Iterate through all possible dividing points
    for (let i = start; i < end; i++) {
        // Find the optimal value of the left part
        const left = optimal(nums, start, i);
 
        // Find the optimal value of the right part
        const right = optimal(nums, i + 1, end);
 
        // Find the minimum value of the expression
        if (t.min_val > left.min_val / right.max_val) {
            t.min_val = left.min_val / right.max_val;
            t.min_str = left.min_str + '/' + (i + 1 !== end ? '(' : '') + right.max_str + (i + 1 !== end ? ')' : '');
        }
 
        // Find the maximum value of the expression
        if (t.max_val < left.max_val / right.min_val) {
            t.max_val = left.max_val / right.min_val;
            t.max_str = left.max_str + '/' + (i + 1 !== end ? '(' : '') + right.min_str + (i + 1 !== end ? ')' : '');
        }
    }
 
    // Return the value of t
    return t;
}
 
// Function to return the string representation
// of the maximum value of the expression
function optimalDivision(nums) {
    const n = nums.length;
    const t = optimal(nums, 0, n - 1);
    return t.max_str;
}
 
// Driver code
    const nums = [1000, 100, 10, 2];
    console.log(optimalDivision(nums));
 
//This code is contributed by aeroabrar_31


Output

1000/(100/10/2)

Time Complexity: O(n!). The number of permutations of expression after applying brackets will be in O(n!)where n is the number of items in the list.
Space Complexity: O(n2). The depth of the recursion tree will be O(n) and each node contains a string of maximum length O(n).

Approach: The idea is based on the observation that for every division, the result is maximum only when the denominator is minimum. Therefore, the task reduces to placing the parentheses and operators in such a way that the denominator is minimum. Consider the following example to solve the problem:

Consider an expression 1000 / 100 / 10 / 2.
To make its value maximum, denominator needs to be minimized. Therefore, the denominators need to be in the sequence 100, 10, 2.
Now, consider the following cases:

  • 100 / (10 / 2) = (100 × 2) / 10 = 20
  • (100 / 10) / 2 = 10 / 2 = 5

Therefore, the minimized value for the expression is obtained for the second case. Therefore, 1000 / (100 / 10 / 2) is the required sequence.

Therefore, from the above example, it can be concluded that the parenthesis needs to be placed to the sequence after the first integer that makes the whole sequence from the second integer reduced to the minimum value possible. 
Follow the steps below to solve the problem:

  • Initialize a string S as “”, to store the final expression.
  • If N is equal to 1, print the integer in string form.
  • Otherwise, append arr[0] and “/(“ in S, and then append all the remaining integers of arr[] separated by “/”.
  • At last, append “)” in the string S and print the string S as the result.

Below is the implementation of the above approach:

C++14




// C++ program for the above approach
#include <bits/stdc++.h>
using namespace std;
 
// Function to place the parenthesis
// such that the result is maximized
void generateSequence(int arr[], int n)
{
    // Store the required string
    string ans;
 
    // Add the first integer to string
    ans = to_string(arr[0]);
 
    // If the size of array is 1
    if (n == 1)
        cout << ans;
 
    // If the size of array is 2, print
    // the 1st integer followed by / operator
    // followed by the next integer
    else if (n == 2) {
        cout << ans + "/"
             << to_string(arr[1]);
    }
 
    // If size of array is exceeds two,
    // print 1st integer concatenated
    // with operators '/', '(' and next
    // integers with the operator '/'
    else {
        ans += "/(" + to_string(arr[1]);
 
        for (int i = 2; i < n; i++) {
            ans += "/" + to_string(arr[i]);
        }
 
        // Add parenthesis at the end
        ans += ")";
 
        // Print the final expression
        cout << ans;
    }
}
 
// Driver Code
int main()
{
    int arr[] = { 1000, 100, 10, 2 };
    int N = sizeof(arr) / sizeof(arr[0]);
    generateSequence(arr, N);
 
    return 0;
}


Java




// Java program for the above approach
import java.io.*;
class GFG
{
 
// Function to place the parenthesis
// such that the result is maximized
static void generateSequence(int arr[], int n)
{
   
    // Store the required string
    String ans;
 
    // Add the first integer to string
    ans = Integer.toString(arr[0]);
 
    // If the size of array is 1
    if (n == 1)
        System.out.println(ans);
 
    // If the size of array is 2, print
    // the 1st integer followed by / operator
    // followed by the next integer
    else if (n == 2) {
        System.out.println(ans + "/"
            + Integer.toString(arr[1]));
    }
 
    // If size of array is exceeds two,
    // print 1st integer concatenated
    // with operators '/', '(' and next
    // integers with the operator '/'
    else {
        ans += "/(" + Integer.toString(arr[1]);
 
        for (int i = 2; i < n; i++) {
            ans += "/" + Integer.toString(arr[i]);
        }
 
        // Add parenthesis at the end
        ans += ")";
 
        // Print the final expression
        System.out.println(ans);
    }
}
 
 
// Driver Code
public static void main(String[] args)
{
    int arr[] = { 1000, 100, 10, 2 };
    int N = arr.length;
    generateSequence(arr, N);
}
}
 
// This code is contributed by code_hunt.


Python3




# Python3 program for the above approach
 
# Function to place the parenthesis
# such that the result is maximized
def generateSequence(arr, n):
     
    # Store the required string
    ans = ""
 
    # Add the first integer to string
    ans = str(arr[0])
 
    # If the size of array is 1
    if (n == 1):
        print(ans)
 
    # If the size of array is 2, print
    # the 1st integer followed by / operator
    # followed by the next integer
    elif (n == 2):
        print(ans + "/"+str(arr[1]))
     
    # If size of array is exceeds two,
    # pr1st integer concatenated
    # with operators '/', '(' and next
    # integers with the operator '/'
    else:
        ans += "/(" + str(arr[1])
 
        for i in range(2, n):
            ans += "/" + str(arr[i])
 
        # Add parenthesis at the end
        ans += ")"
 
        # Print final expression
        print(ans)
 
# Driver Code
if __name__ == '__main__':
    arr = [1000, 100, 10, 2]
    N = len(arr)
    generateSequence(arr, N)
 
    # This code is contributed by mohit kumar 29.


C#




// C# program for the above approach
using System;
class GFG
{
 
// Function to place the parenthesis
// such that the result is maximized
static void generateSequence(int []arr, int n)
{
   
    // Store the required string
    string ans="";
 
    // Add the first integer to string
    ans = arr[0].ToString();
 
    // If the size of array is 1
    if (n == 1)
        Console.WriteLine(ans);
 
    // If the size of array is 2, print
    // the 1st integer followed by / operator
    // followed by the next integer
    else if (n == 2) {
        Console.WriteLine(ans + "/"
            + arr[1].ToString());
    }
 
    // If size of array is exceeds two,
    // print 1st integer concatenated
    // with operators '/', '(' and next
    // integers with the operator '/'
    else {
        ans += "/(" + arr[1].ToString();
 
        for (int i = 2; i < n; i++) {
            ans += "/" + arr[i].ToString();
        }
 
        // Add parenthesis at the end
        ans += ")";
 
        // Print the final expression
        Console.WriteLine(ans);
    }
}
 
// Driver Code
public static void Main(string[] args)
{
    int []arr = { 1000, 100, 10, 2 };
    int N = arr.Length;
    generateSequence(arr, N);
}
}
 
// This code is contributed by chitranayal.


Javascript




<script>
 
// Javascript program for the above approach
 
// Function to place the parenthesis
// such that the result is maximized
function generateSequence(arr, n)
{
    // Store the required string
    var ans;
 
    // Add the first integer to string
    ans = (arr[0].toString());
 
    // If the size of array is 1
    if (n == 1)
        document.write( ans);
 
    // If the size of array is 2, print
    // the 1st integer followed by / operator
    // followed by the next integer
    else if (n == 2) {
        document.write( ans + "/"
             + (arr[1].toString()));
    }
 
    // If size of array is exceeds two,
    // print 1st integer concatenated
    // with operators '/', '(' and next
    // integers with the operator '/'
    else {
        ans += "/(" + (arr[1].toString());
 
        for (var i = 2; i < n; i++) {
            ans += "/" + (arr[i].toString());
        }
 
        // Add parenthesis at the end
        ans += ")";
 
        // Print the final expression
        document.write( ans);
    }
}
 
// Driver Code
var arr = [1000, 100, 10, 2];
var N = arr.length;
generateSequence(arr, N);
 
// This code is contributed by noob2000.
</script>


Output

1000/(100/10/2)



Time Complexity: O(N)
Auxiliary Space: O(N)



Last Updated : 29 Aug, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads