Open In App

Minimum Element for Non-Positive Array in Limited Moves

Last Updated : 27 Dec, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Given the array arr[] and another integer max_moves, Find the minimum possible integer x that must be chosen such that all the elements of the array can be made non-positive in most max_moves operations. In each operation, decrease any element of the array by x.

Examples:

Input: n = 3, arr = [1, 2, 3], max_moves = 4,
Output: 2
Explanation: If the chosen x=1, then we can decrease each element by 1 per operation and it would take a total of 6 moves to make all the elements non-positive which exceeds the max moves allowed

  • If the chosen x=2 then :
  • In the first operation, we decrease the first element. The array becomes (-1,23]
  • In the second operation, we decrease the second element. The array becomes (1.0.3).
  • In the third operation, we decrease the third element. The array becomes (-1,0.1]
  • In the fourth operation, we decrease the third element again. The array becomes [-1.0,-1)

Hence, x = 2 is the minimum possible integer respecting the given conditions. Thus, the answer is 2.

Input: n = 4, arr = (4, 3, 2, 7], max_moves = 5.
Output: 4
Explanation:

  • If we choose x=1, it will take 16 operations to make all the integers non-positive
  • If we choose x=2, it will take 9 operations to make all the integers non-positive
  • If we choose x=3, it will take operations to make all the integers non-positive
  • If we choose x=4, it will take 5 operations to make all the integers non-positive

Hence, x = 4 is the minimum possible decrement that meets the given conditions.

Approach: To solve the problem follow the below idea:

We can observe that when the value of x is small the total operations required are more and when value of x is large total operations required are less. Once you get some valid x then you will always satisfy equation for all values >= x, let’s call it the starting point of success.

Iterate from all values 1 till you reach y and become successful and y will be your answer.

Steps to solve the problem:

  • Initialized two variables i = 0 (loop counter) and g = 0 (total number of operations)
  • While loop that iterates through each element of the array arr[].
  • Inside the while loop, the code checks for two cases positive and negative array element.
  • if the current element arr[i] is divisible by the current value of x without any remainder (arr[i] % x == 0).
  • If it is divisible, it calculates (arr[i] / x) and adds this value to g. This represents the number of operations needed to divide arr[i] by x.
  • If it’s not divisible, it calculates (arr[i] / x) + 1 and adds this value to g. This represents the number of operations needed to divide arr[i] by x and round up to the nearest integer.
  • If the array element is negative then take (abs(arr[i]) / x) + 1.
  • After processing all elements in the array, the code checks if the total number of operations g is less than or equal to the specified maximum number of operations max_moves.
  • If this condition is met, it returns true, indicating that the current value of x satisfies the condition.
  • If the condition is not met (i.e., g exceeds max_moves), the function returns false, indicating that the current value of x does not satisfy the condition.

Below is the C++ implementation of the above approach:

C++




// C++ code for the above approach:
#include <iostream>
using namespace std;
typedef long long int ll;
 
// Function to check if a given 'x' value
// satisfies the condition
bool f(ll x, ll max_moves, ll arr[], ll n)
{
    ll i = 1;
    ll g = 0;
 
    // Iterate through the array to calculate
    // the total operations 'g'
    while (i <= n) {
        if (arr[i] >= 0) {
            if (arr[i] % x == 0) {
                g += arr[i] / x;
            }
            else {
                g += (arr[i] / x) + 1;
            }
        }
        else {
 
            // For negative elements,
            // use ceil(arr[i] / x)
            g += (abs(arr[i]) / x) + 1;
        }
        i++;
    }
 
    // Check if 'g' is within the allowed
    // maximum operations 'max_moves'
    if (g <= max_moves) {
 
        // 'x' satisfies the condition
        return true;
    }
 
    // 'x' does not satisfy the condition
    return false;
}
 
// Drivers code
int main()
{
 
    // Specific case: n = 4
    ll n = 4;
 
    // Specific case: arr = [4, 3, 2, 7]
    ll arr[] = { 0, 4, 3, 2, 7 };
    ll max_moves = 5;
 
    ll i = 1;
 
    // Iterate to find the smallest 'x' that
    // satisfies the condition
    while (f(i, max_moves, arr, n) == false) {
        i++;
    }
 
    // Print the smallest 'x' that
    // satisfies the condition
    cout << i;
 
    return 0;
}


Java




import java.util.Scanner;
 
public class GFG {
    // Function to check if a given 'x' value satisfies the condition
    static boolean f(long x, long max_moves, long[] arr, int n) {
        int i = 1;
        long g = 0;
 
        // Iterate through the array to calculate the total operations 'g'
        while (i <= n) {
            if (arr[i] >= 0) {
                if (arr[i] % x == 0) {
                    g += arr[i] / x;
                } else {
                    g += (arr[i] / x) + 1;
                }
            } else {
                // For negative elements, use ceil(arr[i] / x)
                g += (Math.abs(arr[i]) / x) + 1;
            }
            i++;
        }
 
        // Check if 'g' is within the allowed maximum operations 'max_moves'
        if (g <= max_moves) {
            // 'x' satisfies the condition
            return true;
        }
 
        // 'x' does not satisfy the condition
        return false;
    }
 
    // Main function
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
 
        // Specific case: n = 4
        int n = 4;
 
        // Specific case: arr = [4, 3, 2, 7]
        long[] arr = {0, 4, 3, 2, 7};
        long max_moves = 5;
 
        long i = 1;
 
        // Iterate to find the smallest 'x' that satisfies the condition
        while (!f(i, max_moves, arr, n)) {
            i++;
        }
 
        // Print the smallest 'x' that satisfies the condition
        System.out.println(i);
    }
}


Python3




# Python code for the above approach:
 
# Function to check if a given 'x' value
# satisfies the condition
def is_satisfying(x, max_moves, arr):
    i = 0  # Start from the first element (0-indexed)
    g = 0
 
    # Iterate through the array to calculate
    # the total operations 'g'
    while i < len(arr):
        if arr[i] >= 0:
            if arr[i] % x == 0:
                g += arr[i] // x
            else:
                g += (arr[i] // x) + 1
        else:
            # For negative elements,
            # use ceil(arr[i] / x)
            g += (abs(arr[i]) // x) + 1
        i += 1
 
    # Check if 'g' is within the allowed
    # maximum operations 'max_moves'
    if g <= max_moves:
        # 'x' satisfies the condition
        return True
 
    # 'x' does not satisfy the condition
    return False
 
# Driver code
if __name__ == "__main__":
    # Specific case: n = 4
    n = 4
 
    # Specific case: arr = [4, 3, 2, 7]
    arr = [0, 4, 3, 2, 7]
    max_moves = 5
 
    i = 1
 
    # Iterate to find the smallest 'x' that
    # satisfies the condition
    while not is_satisfying(i, max_moves, arr):
        i += 1
 
    # Print the smallest 'x' that satisfies the condition
    print(i)


C#




// C# code for the above approach
 
using System;
 
public class GFG {
    // Function to check if a given 'x' value satisfies the
    // condition
    static bool f(long x, long max_moves, long[] arr, int n)
    {
        int i = 1;
        long g = 0;
 
        // Iterate through the array to calculate the total
        // operations 'g'
        while (i <= n) {
            if (arr[i] >= 0) {
                if (arr[i] % x == 0) {
                    g += arr[i] / x;
                }
                else {
                    g += (arr[i] / x) + 1;
                }
            }
            else {
                // For negative elements, use ceil(arr[i] /
                // x)
                g += (Math.Abs(arr[i]) / x) + 1;
            }
            i++;
        }
 
        // Check if 'g' is within the allowed maximum
        // operations 'max_moves'
        if (g <= max_moves) {
            // 'x' satisfies the condition
            return true;
        }
 
        // 'x' does not satisfy the condition
        return false;
    }
 
    // Main function
    public static void Main()
    {
 
        // Specific case: n = 4
        int n = 4;
 
        // Specific case: arr = [4, 3, 2, 7]
        long[] arr = { 0, 4, 3, 2, 7 };
        long max_moves = 5;
 
        long i = 1;
 
        // Iterate to find the smallest 'x' that satisfies
        // the condition
        while (!f(i, max_moves, arr, n)) {
            i++;
        }
 
        // Print the smallest 'x' that satisfies the
        // condition
        Console.WriteLine(i);
    }
}
 
// This code is contributed by ragul21


Javascript




// Javascript code for the above approach
 
// Function to check if a given 'x' value satisfies the condition
function f(x, max_moves, arr, n) {
    let i = 1;
    let g = 0;
 
    // Iterate through the array to calculate the total operations 'g'
    while (i <= n) {
        if (arr[i] >= 0) {
            if (arr[i] % x === 0) {
                g += Math.floor(arr[i] / x);
            } else {
                g += Math.floor(arr[i] / x) + 1;
            }
        } else {
            // For negative elements, use ceil(arr[i] / x)
            g += Math.floor(Math.abs(arr[i]) / x) + 1;
        }
        i++;
    }
 
    // Check if 'g' is within the allowed maximum operations 'max_moves'
    if (g <= max_moves) {
        // 'x' satisfies the condition
        return true;
    }
 
    // 'x' does not satisfy the condition
    return false;
}
 
// Driver code
 
// Specific case: n = 4
let n = 4;
 
// Specific case: arr = [4, 3, 2, 7]
let arr = [0, 4, 3, 2, 7];
let max_moves = 5;
 
let i = 1;
 
// Iterate to find the smallest 'x' that satisfies the condition
while (!f(i, max_moves, arr, n)) {
    i++;
}
 
// Print the smallest 'x' that satisfies the condition
console.log(i);
 
// This code is contributed by ragul21


Output

4









Time Complexity: O(n*max element of array), where n is array size.
Auxiliary Space: O(1), as we are not using any extra space.

Efficient Approach: To solve the problem follow the below idea:

Using Binary search to efficiently find the solution that minimizes the number of moves while finding the maximum allowed moves (max_moves). It uses the ‘fun’ function to check if a given value of x is a valid solution.

  • Initialize low to 1, high to the maximum value in arr[], and kk to 0.
  • Enter a loop while low is less than or equal to high and kk is 0.
  • Calculate the midpoint mid.
  • If fun(mid, k, b, n) is true:
  • If mid is 1, set answer to 1 and exit the loop and If mid-1 is not a valid solution, set answer to mid and exit, otherwise, update high to mid – 1.
  • If fun(mid, max_moves, arr, n) is false, update low to mid + 1.
  • Exit the loop when kk becomes 1 or low is greater than high.
  • Print the answer, representing the smallest x satisfying the condition.

Below is the implementation of the above idea:

C++




// C++ code for the above approach:
#include <algorithm>
#include <cmath>
#include <iostream>
#include <vector>
 
using namespace std;
 
bool fun(vector<int>& arr, int x, int max_moves)
{
    int moves = 0;
    for (int num : arr) {
        if (num >= 0) {
            if (num % x == 0) {
                moves += num / x;
            }
            else {
                moves += (num / x) + 1;
            }
        }
        else {
            // For negative elements, use
            // ceil(num / x) and subtract
            // 1 from moves
            moves += (abs(num) / x) + 1;
        }
    }
    return moves <= max_moves;
}
 
int findMinimumX(vector<int>& arr, int max_moves)
{
 
    // Minimum possible x
    int left = 1;
 
    // Maximum possible x
    int right = *max_element(arr.begin(), arr.end());
 
    while (left < right) {
        int mid = left + (right - left) / 2;
        if (fun(arr, mid, max_moves)) {
            right = mid;
        }
        else {
            left = mid + 1;
        }
    }
 
    return left;
}
 
// Drivers code
int main()
{
    int n = 4;
    vector<int> arr = { 0, 4, 3, 2, 7 };
    int max_moves = 5;
 
    // Function Call
    int result = findMinimumX(arr, max_moves);
    cout << result << endl;
 
    return 0;
}


Java




// Java code for the above approach:
 
import java.util.Arrays;
 
class GFG {
 
    static boolean fun(int[] arr, int x, int max_moves)
    {
        int moves = 0;
 
        for (int num : arr) {
            if (num >= 0) {
                if (num % x == 0) {
                    moves += num / x;
                }
                else {
                    moves += (num / x) + 1;
                }
            }
            else {
                // For negative elements, use
                // ceil(num / x) and subtract
                // 1 from moves
                moves += (Math.abs(num) / x) + 1;
            }
        }
 
        return moves <= max_moves;
    }
 
    static int findMinimumX(int[] arr, int max_moves)
    {
 
        // Minimum possible x
        int left = 1;
 
        // Maximum possible x
        int right = Arrays.stream(arr).max().getAsInt();
 
        while (left < right) {
            int mid = left + (right - left) / 2;
 
            if (fun(arr, mid, max_moves)) {
                right = mid;
            }
            else {
                left = mid + 1;
            }
        }
 
        return left;
    }
 
    // Drivers code
    public static void main(String[] args)
    {
        int n = 4;
        int[] arr = { 0, 4, 3, 2, 7 };
        int max_moves = 5;
 
        // Function Call
        int result = findMinimumX(arr, max_moves);
        System.out.println(result);
    }
}
 
// This code is contributed by ragul21


Python3




import math
 
# Function to check if the given value of x
# satisfies the condition within max_moves
def fun(arr, x, max_moves):
    moves = 0
    for num in arr:
        if num >= 0:
            # For non-negative elements, calculate moves
            # based on whether num is divisible by x or not
            moves += num // x if num % x == 0 else (num // x) + 1
        else:
            # For negative elements, use ceil(abs(num) / x) and subtract 1 from moves
            moves += (abs(num) // x) + 1
    return moves <= max_moves
 
# Function to find the minimum possible x
def findMinimumX(arr, max_moves):
    # Minimum possible x
    left = 1
    # Maximum possible x is the maximum element in the array
    right = max(arr)
 
    # Binary search to find the minimum x that satisfies the condition
    while left < right:
        mid = left + (right - left) // 2
        if fun(arr, mid, max_moves):
            right = mid
        else:
            left = mid + 1
 
    return left
 
# Drivers code
if __name__ == "__main__":
    n = 4
    arr = [0, 4, 3, 2, 7]
    max_moves = 5
 
    # Function Call
    result = findMinimumX(arr, max_moves)
    print(result)


C#




using System;
using System.Collections.Generic;
using System.Linq;
 
class Program
{
    static bool Fun(List<int> arr, int x, int maxMoves)
    {
        int moves = 0;
        foreach (int num in arr)
        {
            if (num >= 0)
            {
                if (num % x == 0)
                {
                    moves += num / x;
                }
                else
                {
                    moves += (num / x) + 1;
                }
            }
            else
            {
                moves += (Math.Abs(num) / x) + 1;
            }
        }
        return moves <= maxMoves;
    }
 
    static int FindMinimumX(List<int> arr, int maxMoves)
    {
        int left = 1;
        int right = arr.Max();
 
        while (left < right)
        {
            int mid = left + (right - left) / 2;
            if (Fun(arr, mid, maxMoves))
            {
                right = mid;
            }
            else
            {
                left = mid + 1;
            }
        }
 
        return left;
    }
 
    static void Main()
    {
        List<int> arr = new List<int> { 0, 4, 3, 2, 7 };
        int maxMoves = 5;
 
        int result = FindMinimumX(arr, maxMoves);
        Console.WriteLine(result);
    }
}


Javascript




function fun(arr, x, max_moves) {
    let moves = 0;
 
    for (let num of arr) {
        if (num >= 0) {
            if (num % x === 0) {
                moves += num / x;
            } else {
                moves += Math.floor(num / x) + 1;
            }
        } else {
            // For negative elements, use
            // Math.ceil(Math.abs(num) / x) and subtract
            // 1 from moves
            moves += Math.floor(Math.abs(num) / x) + 1;
        }
    }
 
    return moves <= max_moves;
}
 
function findMinimumX(arr, max_moves) {
    // Minimum possible x
    let left = 1;
 
    // Maximum possible x
    let right = Math.max(...arr);
 
    while (left < right) {
        let mid = left + Math.floor((right - left) / 2);
 
        if (fun(arr, mid, max_moves)) {
            right = mid;
        } else {
            left = mid + 1;
        }
    }
 
    return left;
}
 
// Drivers code
let arr = [0, 4, 3, 2, 7];
let max_moves = 5;
 
// Function Call
let result = findMinimumX(arr, max_moves);
console.log(result);
 
// This code is contributed by Gaurav Arora


Output

4










Time Complexity: O(n * log(max_element)), where n is array size.
Auxiliary Space: O(1), as we are not using any extra space.



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads