Generate a sequence such that float division of array elements is maximized
Last Updated :
29 Aug, 2023
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:
- 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.
- 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.
- 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.
- Otherwise, create an instance of the T struct and initialize min_val to FLT_MAX and max_val to FLT_MIN.
- 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.
- 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 “)”.
- 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 “)”.
- After looping through all possible dividing points, return the instance of the T struct that has the maximum value of the expression.
- 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++
#include <bits/stdc++.h>
using namespace std;
struct T {
float max_val, min_val;
string min_str, max_str;
};
T optimal( int nums[], int start, int end)
{
T t;
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 = "" ;
for ( int i = start; i < end; i++) {
T left = optimal(nums, start, i);
T right = optimal(nums, i + 1, end);
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 ? ")" : "" );
}
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 t;
}
string optimalDivision( int nums[], int n)
{
T t = optimal(nums, 0, n - 1);
return t.max_str;
}
int main()
{
int nums[] = { 1000, 100, 10, 2 };
int n = sizeof (nums) / sizeof (nums[0]);
cout << optimalDivision(nums, n);
return 0;
}
|
Java
import java.util.*;
class T {
float max_val, min_val;
String min_str, max_str;
}
class GFG {
public static T optimal( int nums[], int start, int end)
{
T t = new T();
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 = "" ;
for ( int i = start; i < end; i++) {
T left = optimal(nums, start, i);
T right = optimal(nums, i + 1 , end);
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 ? ")" : "" );
}
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 t;
}
public static String optimalDivision( int nums[], int n)
{
T t = optimal(nums, 0 , n - 1 );
return t.max_str;
}
public static void main(String args[])
{
int nums[] = { 1000 , 100 , 10 , 2 };
int n = nums.length;
System.out.println(optimalDivision(nums, n));
}
}
|
Python3
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 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
for i in range (start, end):
left = optimal(nums, start, i)
right = optimal(nums, i + 1 , end)
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 + = ")"
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 t
def optimal_division(nums):
n = len (nums)
t = optimal(nums, 0 , n - 1 )
return t.max_str
if __name__ = = "__main__" :
nums = [ 1000 , 100 , 10 , 2 ]
print (optimal_division(nums))
|
C#
using System;
class T {
public float max_val, min_val;
public string min_str, max_str;
}
class GFG {
public static T Optimal( int [] nums, int start, int end)
{
T t = new T();
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 = "" ;
for ( int i = start; i < end; i++) {
T left = Optimal(nums, start, i);
T right = Optimal(nums, i + 1, end);
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 ? ")" : "" );
}
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 t;
}
public static string OptimalDivision( int [] nums, int n)
{
T t = Optimal(nums, 0, n - 1);
return t.max_str;
}
public static void Main( string [] args)
{
int [] nums = { 1000, 100, 10, 2 };
int n = nums.Length;
Console.WriteLine(OptimalDivision(nums, n));
}
}
|
Javascript
class T {
constructor() {
this .max_val = 0;
this .min_val = 0;
this .min_str = '' ;
this .max_str = '' ;
}
}
function optimal(nums, start, end) {
const t = new T();
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 = '' ;
for (let i = start; i < end; i++) {
const left = optimal(nums, start, i);
const right = optimal(nums, i + 1, end);
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 ? ')' : '' );
}
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 t;
}
function optimalDivision(nums) {
const n = nums.length;
const t = optimal(nums, 0, n - 1);
return t.max_str;
}
const nums = [1000, 100, 10, 2];
console.log(optimalDivision(nums));
|
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
#include <bits/stdc++.h>
using namespace std;
void generateSequence( int arr[], int n)
{
string ans;
ans = to_string(arr[0]);
if (n == 1)
cout << ans;
else if (n == 2) {
cout << ans + "/"
<< to_string(arr[1]);
}
else {
ans += "/(" + to_string(arr[1]);
for ( int i = 2; i < n; i++) {
ans += "/" + to_string(arr[i]);
}
ans += ")" ;
cout << ans;
}
}
int main()
{
int arr[] = { 1000, 100, 10, 2 };
int N = sizeof (arr) / sizeof (arr[0]);
generateSequence(arr, N);
return 0;
}
|
Java
import java.io.*;
class GFG
{
static void generateSequence( int arr[], int n)
{
String ans;
ans = Integer.toString(arr[ 0 ]);
if (n == 1 )
System.out.println(ans);
else if (n == 2 ) {
System.out.println(ans + "/"
+ Integer.toString(arr[ 1 ]));
}
else {
ans += "/(" + Integer.toString(arr[ 1 ]);
for ( int i = 2 ; i < n; i++) {
ans += "/" + Integer.toString(arr[i]);
}
ans += ")" ;
System.out.println(ans);
}
}
public static void main(String[] args)
{
int arr[] = { 1000 , 100 , 10 , 2 };
int N = arr.length;
generateSequence(arr, N);
}
}
|
Python3
def generateSequence(arr, n):
ans = ""
ans = str (arr[ 0 ])
if (n = = 1 ):
print (ans)
elif (n = = 2 ):
print (ans + "/" + str (arr[ 1 ]))
else :
ans + = "/(" + str (arr[ 1 ])
for i in range ( 2 , n):
ans + = "/" + str (arr[i])
ans + = ")"
print (ans)
if __name__ = = '__main__' :
arr = [ 1000 , 100 , 10 , 2 ]
N = len (arr)
generateSequence(arr, N)
|
C#
using System;
class GFG
{
static void generateSequence( int []arr, int n)
{
string ans= "" ;
ans = arr[0].ToString();
if (n == 1)
Console.WriteLine(ans);
else if (n == 2) {
Console.WriteLine(ans + "/"
+ arr[1].ToString());
}
else {
ans += "/(" + arr[1].ToString();
for ( int i = 2; i < n; i++) {
ans += "/" + arr[i].ToString();
}
ans += ")" ;
Console.WriteLine(ans);
}
}
public static void Main( string [] args)
{
int []arr = { 1000, 100, 10, 2 };
int N = arr.Length;
generateSequence(arr, N);
}
}
|
Javascript
<script>
function generateSequence(arr, n)
{
var ans;
ans = (arr[0].toString());
if (n == 1)
document.write( ans);
else if (n == 2) {
document.write( ans + "/"
+ (arr[1].toString()));
}
else {
ans += "/(" + (arr[1].toString());
for ( var i = 2; i < n; i++) {
ans += "/" + (arr[i].toString());
}
ans += ")" ;
document.write( ans);
}
}
var arr = [1000, 100, 10, 2];
var N = arr.length;
generateSequence(arr, N);
</script>
|
Time Complexity: O(N)
Auxiliary Space: O(N)
Similar Reads
Maximize the Sum of a Subsequence from an Array based on given conditions
Given an array a[] consisting of N integers, the task is to perform the following operations: Select a subsequence and for every pth element of the subsequence, calculate the product p * a[i].Calculate the sum of the calculated values of p * a[i].The subsequence should be selected such that it maxim
7 min read
Minimize divisions such that no Array element is divisible by K
Given an array arr[] of size N and an integer K, the task is to find the minimum operations such that no variable is divisible by K. In each operation: Select any integer X from the array.Divide all occurrences of X by K. Examples: Input: arr[] = [2, 3, 4, 5], K = 2Output: 2Explanation:In the first
6 min read
Generate elements of the array following given conditions
Given an integer N, for every integer i in the range 2 to N, assign a positive integer [Tex]a_i [/Tex]such that the following conditions hold : For any pair of indices (i, j), if i and j are coprime then [Tex]a_i \neq a_j [/Tex].The maximum value of all [Tex]a_i [/Tex]should be minimized (i.e. max v
6 min read
Remove an element to maximize the GCD of the given array
Given an array arr[] of length N ⥠2. The task is to remove an element from the given array such that the GCD of the array after removing it is maximized. Examples: Input: arr[] = {12, 15, 18} Output: 6 Remove 12: GCD(15, 18) = 3 Remove 15: GCD(12, 18) = 6 Remove 18: GCD(12, 15) = 3 Input: arr[] = {
13 min read
Minimize count of divisions by 2 required to make all array elements equal
Given an array arr[] consisting of N positive integers, the task is to find the minimum count of divisions(integer division) of array elements by 2 to make all array elements the same. Examples: Input: arr[] = {3, 1, 1, 3}Output: 2Explanation:Operation 1: Divide arr[0] ( = 3) by 2. The array arr[] m
8 min read
Maximum subsequence sum such that all elements are K distance apart
Given an array arr[] of N integers and another integer K. The task is to find the maximum sum of a subsequence such that the difference of the indices of all consecutive elements in the subsequence in the original array is exactly K. For example, if arr[i] is the first element of the subsequence the
10 min read
Maximize the first element of the array such that average remains constant
Given an array arr[] of length N and an integer X, the task is to find the maximum value R of updated first element such that the average of the array remains constant and no elements of the array should become negative. The maximum value of the first element should be in the range arr[0] <= R
6 min read
Maximize length of longest increasing prime subsequence from the given array
Given an array, arr[] of size N, the task is to find the length of the longest increasing prime subsequence possible by performing the following operations. If arr[i] is already a prime number, no need to update arr[i].Update non-prime arr[i] to the closest prime number less than arr[i].Update non-p
13 min read
Generate a sequence with product N such that for every pair of indices (i, j) and i < j, arr[j] is divisible by arr[i]
Given a positive integer N, the task is to generate a sequence say arr[] of maximum length having all elements at least 2 such that the product of all the numbers in the sequence is N and for any pair of indices (i, j) and i < j, arr[j] is divisible by arr[i]. Examples: Input: N = 360Output: Maxi
11 min read
Maximum sub-sequence sum such that indices of any two adjacent elements differs at least by 3
Given an array arr[] of integers, the task is to find the maximum sum of any sub-sequence in the array such that any two adjacent elements in the selected sequence have at least a difference of 3 in their indices in the given array. In other words, if you select arr[i] then the next element you can
12 min read