📌  相关文章
📜  最小可能值T,使得最多具有总和T的数组的最多D个分区成为可能

📅  最后修改于: 2021-05-17 02:51:24             🧑  作者: Mango

给定一个由N个整数和一个整数D组成的数组arr [] ,任务是找到最小的整数T ,以便整个数组可以从给定数组的总和最大为T的情况下划分为最多D个子数组。

例子:

天真的方法:这个想法是检查在[max(element),sum(element)]范围内T的所有可能值是否最多可以有D个分区。

时间复杂度: O(N * R)
辅助空间: O(1)

高效的方法:想法是使用二进制搜索来优化上述方法。请按照以下步骤解决问题:

  • 考虑范围R = [max(element),sum(element)]中的T。
  • 如果中位数T最多可以生成D个分区,则检查中位数是否小于T。
  • 否则,检查中位数是否大于当前中位数T。
  • 最后返回T的可能值。

下面是上述方法的实现:

C++
// C++ Program for the above approach
#include 
using namespace std;
  
// Funtion to check if the array
// can be partitioned into atmost d
// subarray with sum atmost T
bool possible(int T, int arr[], int n, int d)
{
    // Initial partition
    int partition = 1;
  
    // Current sum
    int total = 0;
  
    for (int i = 0; i < n; i++) {
  
        total = total + arr[i];
  
        // If current sum exceeds T
        if (total > T) {
  
            // Create a new partition
            partition = partition + 1;
            total = arr[i];
  
            // If count of partitions
            // exceed d
            if (partition > d) {
                return false;
            }
        }
    }
  
    return true;
}
  
// Function to find the minimum
// possible value of T
void calcT(int n, int d, int arr[])
{
    // Stores the maximum and
    // total sum of elements
    int mx = -1, sum = 0;
  
    for (int i = 0; i < n; i++) {
  
        // Maximum element
        mx = max(mx, arr[i]);
  
        // Sum of all elements
        sum = sum + arr[i];
    }
  
    int lb = mx;
    int ub = sum;
  
    while (lb < ub) {
  
        // Calculate median  T
        int T_mid = lb + (ub - lb) / 2;
  
        // If atmost D partitions possible
        if (possible(T_mid, arr, n, d) == true) {
  
            // Check for smaller T
            ub = T_mid;
        }
  
        // Otherwise
        else {
  
            // Check for larger T
            lb = T_mid + 1;
        }
    }
  
    // Print the minimum T required
    cout << lb << endl;
}
  
// Driver Code
int main()
{
    int d = 2;
    int arr[] = { 1, 1, 1, 1, 1 };
  
    int n = sizeof arr / sizeof arr[0];
    // Function call
    calcT(n, d, arr);
  
    return 0;
}


Java
// Java program for the above approach
import java.util.*;
import java.io.*;
  
class GFG{
      
// Function to check if the array
// can be partitioned into atmost d
// subarray with sum atmost T
public static boolean possible(int T, int arr[],
                               int n, int d)
{
      
    // Initial partition
    int partition = 1;
  
    // Current sum
    int total = 0;
  
    for(int i = 0; i < n; i++)
    {
        total = total + arr[i];
  
        // If current sum exceeds T
        if (total > T)
        {
              
            // Create a new partition
            partition = partition + 1;
            total = arr[i];
  
            // If count of partitions
            // exceed d
            if (partition > d)
            {
                return false;
            }
        }
    }
    return true;
}
  
// Function to find the minimum
// possible value of T
public static void calcT(int n, int d,
                         int arr[])
{
      
    // Stores the maximum and
    // total sum of elements
    int mx = -1, sum = 0;
  
    for(int i = 0; i < n; i++)
    {
          
        // Maximum element
        mx = Math.max(mx, arr[i]);
  
        // Sum of all elements
        sum = sum + arr[i];
    }
  
    int lb = mx;
    int ub = sum;
  
    while (lb < ub)
    {
          
        // Calculate median T
        int T_mid = lb + (ub - lb) / 2;
  
        // If atmost D partitions possible
        if (possible(T_mid, arr, n, d) == true)
        {
              
            // Check for smaller T
            ub = T_mid;
        }
  
        // Otherwise
        else
        {
              
            // Check for larger T
            lb = T_mid + 1;
        }
    }
      
    // Print the minimum T required
    System.out.println(lb);
}
  
// Driver code
public static void main(String args[])
{
    int d = 2;
    int arr[] = { 1, 1, 1, 1, 1 };
  
    int n = arr.length;
      
    // Function call
    calcT(n, d, arr);
}
}
  
// This code is contributed by decoding


Python3
# Python3 program for the above approach
  
# Function to check if the array
# can be partitioned into atmost d
# subarray with sum atmost T
def possible(T, arr, n, d):
      
    # Initial partition
    partition = 1;
  
    # Current sum
    total = 0;
  
    for i in range(n):
        total = total + arr[i];
  
        # If current sum exceeds T
        if (total > T):
  
            # Create a new partition
            partition = partition + 1;
            total = arr[i];
  
            # If count of partitions
            # exceed d
            if (partition > d):
                return False;
  
    return True;
  
# Function to find the minimum
# possible value of T
def calcT(n, d, arr):
      
    # Stores the maximum and
    # total sum of elements
    mx = -1; sum = 0;
  
    for i in range(n):
          
        # Maximum element
        mx = max(mx, arr[i]);
  
        # Sum of all elements
        sum = sum + arr[i];
  
    lb = mx;
    ub = sum;
  
    while (lb < ub):
  
        # Calculate median T
        T_mid = lb + (ub - lb) // 2;
  
        # If atmost D partitions possible
        if (possible(T_mid, arr, n, d) == True):
  
            # Check for smaller T
            ub = T_mid;
  
        # Otherwise
        else:
  
            # Check for larger T
            lb = T_mid + 1;
  
    # Print the minimum T required
    print(lb);
  
# Driver code
if __name__ == '__main__':
      
    d = 2;
    arr = [ 1, 1, 1, 1, 1 ];
  
    n = len(arr);
  
    # Function call
    calcT(n, d, arr);
  
# This code is contributed by Rajput-Ji


C#
// C# program for the above approach
using System;
  
class GFG{
      
// Function to check if the array
// can be partitioned into atmost d
// subarray with sum atmost T
public static bool possible(int T, int []arr,
                            int n, int d)
{
      
    // Initial partition
    int partition = 1;
  
    // Current sum
    int total = 0;
  
    for(int i = 0; i < n; i++)
    {
        total = total + arr[i];
  
        // If current sum exceeds T
        if (total > T)
        {
              
            // Create a new partition
            partition = partition + 1;
            total = arr[i];
  
            // If count of partitions
            // exceed d
            if (partition > d)
            {
                return false;
            }
        }
    }
    return true;
}
  
// Function to find the minimum
// possible value of T
public static void calcT(int n, int d,
                         int []arr)
{
      
    // Stores the maximum and
    // total sum of elements
    int mx = -1, sum = 0;
  
    for(int i = 0; i < n; i++)
    {
          
        // Maximum element
        mx = Math.Max(mx, arr[i]);
  
        // Sum of all elements
        sum = sum + arr[i];
    }
  
    int lb = mx;
    int ub = sum;
  
    while (lb < ub)
    {
          
        // Calculate median T
        int T_mid = lb + (ub - lb) / 2;
  
        // If atmost D partitions possible
        if (possible(T_mid, arr, n, d) == true)
        {
              
            // Check for smaller T
            ub = T_mid;
        }
  
        // Otherwise
        else
        {
              
            // Check for larger T
            lb = T_mid + 1;
        }
    }
      
    // Print the minimum T required
    Console.WriteLine(lb);
}
  
// Driver code
public static void Main(String []args)
{
    int d = 2;
    int []arr = { 1, 1, 1, 1, 1 };
  
    int n = arr.Length;
      
    // Function call
    calcT(n, d, arr);
}
}
  
// This code is contributed by 29AjayKumar


输出
3

时间复杂度: O(N * log(sum))
辅助空间: O(1)