Given that there are N books and M students. Also given are the number of pages in each book in ascending order. The task is to assign books in such a way that the maximum number of pages assigned to a student is minimum, with the condition that every student is assigned to read some consecutive books. Print that minimum number of pages.
Example :
Input: N = 4, pages[] = {12, 34, 67, 90}, M = 2
Output: 113
Explanation: There are 2 number of students. Books can be distributed in following combinations:
- [12] and [34, 67, 90] -> Max number of pages is allocated to student ‘2’ with 34 + 67 + 90 = 191 pages
- [12, 34] and [67, 90] -> Max number of pages is allocated to student ‘2’ with 67 + 90 = 157 pages
- [12, 34, 67] and [90] -> Max number of pages is allocated to student ‘1’ with 12 + 34 + 67 = 113 pages
Of the 3 cases, Option 3 has the minimum pages = 113.
Naive Approach: The simplest approach to solve this problem is to find all permutations to distribute N books among M students, and return the minimum page allocation among them.
Efficient Approach:
Another way to solve this problem is to use Binary Search, based on this idea:
Case 1: When no valid answer exists.
- If the number of students is greater than the number of books (i.e, M > N), In this case at least 1 student will be left to which no book has been assigned.
Case 2: When a valid answer exists.
- The maximum possible answer could be when there is only one student. So, all the book will be assigned to him and the result would be the sum of pages of all the books.
- The minimum possible answer could be when number of student is equal to the number of book (i.e, M == N) , In this case all the students will get at most one book. So, the result would be the maximum number of pages among them (i.e, maximum(pages[])).
- Hence, we can apply binary search in this given range and each time we can consider the mid value as the maximum limit of pages one can get. And check for the limit if answer is valid then update the limit accordingly.
Below is the approach to solve this problem using Binary Search:
- Calculate the mid and check if mid number of pages can be assigned to students such that all students will get at least one book.
- If yes, then update the result and check for the previous search space (end = mid-1)
- Otherwise, check for the next search space (start = mid+1)
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
bool isPossible( int arr[], int n, int m, int curr_min)
{
int studentsRequired = 1;
int curr_sum = 0;
for ( int i = 0; i < n; i++) {
if (arr[i] > curr_min)
return false ;
if (curr_sum + arr[i] > curr_min) {
studentsRequired++;
curr_sum = arr[i];
if (studentsRequired > m)
return false ;
}
else
curr_sum += arr[i];
}
return true ;
}
int findPages( int arr[], int n, int m)
{
long long sum = 0;
if (n < m)
return -1;
int mx = INT_MIN;
for ( int i = 0; i < n; i++) {
sum += arr[i];
mx = max(mx, arr[i]);
}
int start = mx, end = sum;
int result = INT_MAX;
while (start <= end) {
int mid = (start + end) / 2;
if (isPossible(arr, n, m, mid)) {
result = mid;
end = mid - 1;
}
else
start = mid + 1;
}
return result;
}
int main()
{
int arr[] = { 12, 34, 67, 90 };
int n = sizeof arr / sizeof arr[0];
int m = 2;
cout << "Minimum number of pages = "
<< findPages(arr, n, m) << endl;
return 0;
}
|
C
#include <limits.h>
#include <stdbool.h>
#include <stdio.h>
bool isPossible( int arr[], int n, int m, int curr_min)
{
int studentsRequired = 1;
int curr_sum = 0;
for ( int i = 0; i < n; i++) {
if (arr[i] > curr_min)
return false ;
if (curr_sum + arr[i] > curr_min) {
studentsRequired++;
curr_sum = arr[i];
if (studentsRequired > m)
return false ;
}
else
curr_sum += arr[i];
}
return true ;
}
int findPages( int arr[], int n, int m)
{
long long sum = 0;
if (n < m)
return -1;
int mx = arr[0];
for ( int i = 0; i < n; i++) {
sum += arr[i];
mx = (arr[i] > mx ? arr[i] : mx);
}
int start = mx, end = sum;
int result = INT_MAX;
while (start <= end) {
int mid = (start + end) / 2;
if (isPossible(arr, n, m, mid)) {
result = mid;
end = mid - 1;
}
else
start = mid + 1;
}
return result;
}
int main()
{
int arr[] = { 12, 34, 67, 90 };
int n = sizeof arr / sizeof arr[0];
int m = 2;
printf ( "Minimum number of pages = %d\n" ,
findPages(arr, n, m));
return 0;
}
|
Java
public class GFG {
static boolean isPossible( int arr[], int n, int m,
int curr_min)
{
int studentsRequired = 1 ;
int curr_sum = 0 ;
for ( int i = 0 ; i < n; i++) {
curr_sum += arr[i];
if (curr_sum > curr_min) {
studentsRequired++;
curr_sum = arr[i];
}
}
return studentsRequired <= m;
}
static int findPages( int arr[], int n, int m)
{
int sum = 0 ;
if (n < m)
return - 1 ;
int mx = arr[ 0 ];
for ( int i = 0 ; i < n; i++) {
sum += arr[i];
mx = (arr[i] > mx ? arr[i] : mx);
}
int start = arr[n - 1 ], end = sum;
int result = Integer.MAX_VALUE;
while (start <= end) {
int mid = start + (end - start) / 2 ;
if (isPossible(arr, n, m, mid)) {
result = mid;
end = mid - 1 ;
}
else
start = mid + 1 ;
}
return result;
}
public static void main(String[] args)
{
int arr[] = { 12 , 34 , 67 ,
90 };
int m = 2 ;
System.out.println( "Minimum number of pages = "
+ findPages(arr, arr.length, m));
}
}
|
Python3
def isPossible(arr, n, m, curr_min):
studentsRequired = 1
curr_sum = 0
for i in range (n):
if (arr[i] > curr_min):
return False
if (curr_sum + arr[i] > curr_min):
studentsRequired + = 1
curr_sum = arr[i]
if (studentsRequired > m):
return False
else :
curr_sum + = arr[i]
return True
def findPages(arr, n, m):
sum = 0
if (n < m):
return - 1
for i in range (n):
sum + = arr[i]
start, end = 0 , sum
result = 10 * * 9
while (start < = end):
mid = (start + end) / / 2
if (isPossible(arr, n, m, mid)):
result = mid
end = mid - 1
else :
start = mid + 1
return result
arr = [ 12 , 34 , 67 , 90 ]
n = len (arr)
m = 2
print ( "Minimum number of pages = " ,
findPages(arr, n, m))
|
C#
using System;
class GFG {
static bool isPossible( int [] arr, int n, int m,
int curr_min)
{
int studentsRequired = 1;
int curr_sum = 0;
for ( int i = 0; i < n; i++) {
if (arr[i] > curr_min)
return false ;
if (curr_sum + arr[i] > curr_min) {
studentsRequired++;
curr_sum = arr[i];
if (studentsRequired > m)
return false ;
}
else
curr_sum += arr[i];
}
return true ;
}
static int findPages( int [] arr, int n, int m)
{
long sum = 0;
if (n < m)
return -1;
int mx = arr[0];
for ( int i = 0; i < n; i++) {
sum += arr[i];
mx = (arr[i] > mx ? arr[i] : mx);
}
int start = 0, end = ( int )sum;
int result = int .MaxValue;
while (start <= end) {
int mid = (start + end) / 2;
if (isPossible(arr, n, m, mid)) {
result = mid;
end = mid - 1;
}
else
start = mid + 1;
}
return result;
}
static public void Main()
{
int [] arr = { 12, 34, 67, 90 };
int n = arr.Length;
int m = 2;
Console.WriteLine( "Minimum number of pages = "
+ findPages(arr, n, m));
}
}
|
PHP
<?php
function isPossible( $arr , $n , $m ,
$curr_min )
{
$studentsRequired = 1;
$curr_sum = 0;
for ( $i = 0; $i < $n ; $i ++)
{
if ( $arr [ $i ] > $curr_min )
return false;
if ( $curr_sum + $arr [ $i ] > $curr_min )
{
$studentsRequired ++;
$curr_sum = $arr [ $i ];
if ( $studentsRequired > $m )
return false;
}
else
$curr_sum += $arr [ $i ];
}
return true;
}
function findPages( $arr , $n , $m )
{
$sum = 0;
if ( $n < $m )
return -1;
for ( $i = 0; $i < $n ; $i ++)
$sum += $arr [ $i ];
$start = 0;
$end = $sum ;
$result = PHP_INT_MAX;
while ( $start <= $end )
{
$mid = (int)( $start + $end ) / 2;
if (isPossible( $arr , $n , $m , $mid ))
{
$result = $mid ;
$end = $mid - 1;
}
else
$start = $mid + 1;
}
return $result ;
}
$arr = array (12, 34, 67, 90);
$n = count ( $arr );
$m = 2;
echo "Minimum number of pages = " ,
findPages( $arr , $n , $m ), "\n" ;
?>
|
Javascript
function isPossible(arr,n,m,curr_min)
{
let studentsRequired = 1;
let curr_sum = 0;
for (let i = 0; i < n; i++)
{
if (arr[i] > curr_min)
return false ;
if (curr_sum + arr[i] > curr_min)
{
studentsRequired++;
curr_sum = arr[i];
if (studentsRequired > m)
return false ;
}
else
curr_sum += arr[i];
}
return true ;
}
function findPages(arr,n,m)
{
let sum = 0;
int mx = arr[0] ;
if (n < m)
return -1;
for (let i = 0; i < n; i++){
sum += arr[i];
mx = (arr[i] > mx ? arr[i] : mx) ;
}
let start = 0, end = sum;
let result = Number.MAX_VALUE;
while (start <= end)
{
let mid =Math.floor( (start + end) / 2);
if (isPossible(arr, n, m, mid))
{
result = Math.min(result, mid);
end = mid - 1;
}
else
start = mid + 1;
}
return result;
}
let arr=[12, 34, 67, 90];
let m = 2;
console.log( "Minimum number of pages = " +
findPages(arr, arr.length, m));
|
OutputMinimum number of pages = 113
Time Complexity: O(N*log(N)), Where N is the total number of pages in the book.
Auxiliary Space: O(1)