Open In App

Minimum Element for Non-Positive Array in Limited Moves

Last Updated : 27 Dec, 2023
Comments
Improve
Suggest changes
Like Article
Like
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.


Next Article

Similar Reads