There is a school that has classes of students and each class will be having a final exam. You are given a 2D integer arrayclasses, where classes[i] = [passi, totali]. You know beforehand that in the ith class, there are totali total students, but only passi number of students will pass the exam.
You are also given an integer extraStudents. There are another extraStudents brilliant students that are guaranteed to pass the exam of any class they are assigned to. You want to assign each of the extraStudents students to a class in a way that maximizes the average pass ratio across all the classes.
The pass ratio of a class is equal to the number of students of the class that will pass the exam divided by the total number of students of the class. The average pass ratio is the sum of pass ratios of all the classes divided by the number of the classes.
Return the maximum possible average pass ratio after assigning the extraStudents students. Answers within 10⁻⁵ of the actual answer will be accepted.
Input & Output
Example 1 — Basic Assignment
$Input:classes = [[1,2],[3,5]], extraStudents = 2
›Output:0.675
💡 Note:Initially: Class 1 has ratio 1/2=0.5, Class 2 has ratio 3/5=0.6. The improvement from adding one student to Class 1 is (2/3-1/2)=1/6≈0.167, while for Class 2 it's (4/6-3/5)=1/15≈0.067. So we add the first student to Class 1: [2,3]. The new improvements are (3/4-2/3)=1/12≈0.083 for Class 1 and 1/15≈0.067 for Class 2. Class 1 still has better improvement, so we add the second student there too: [3,4]. Final ratios: 3/4=0.75 and 3/5=0.6. Average = (0.75+0.6)/2 = 0.675.
Example 2 — Single Class
$Input:classes = [[2,4]], extraStudents = 1
›Output:0.6
💡 Note:Initially: Class has ratio 2/4 = 0.5. Adding one student gives (3,5) with ratio 3/5 = 0.6. Since there's only one class, the average is 0.6.
Example 3 — No Improvement Needed
$Input:classes = [[3,3],[4,4]], extraStudents = 2
›Output:1.0
💡 Note:Both classes already have 100% pass rate. Adding students maintains 100% pass rate: (4,4) and (5,5) both have ratio 1.0. Average remains 1.0.
The key insight is that we should always assign each extra student to the class that gives the maximum improvement in pass ratio. Using a priority queue to track improvements leads to the optimal greedy solution. Best approach is Greedy with Priority Queue: Time: O(extraStudents × log n), Space: O(n)
Common Approaches
✓
Frequency Count
⏱️ Time: N/A
Space: N/A
Brute Force - Try All Distributions
⏱️ Time: O(n^extraStudents)
Space: O(1)
Generate all possible ways to distribute extraStudents among the classes and calculate the average pass ratio for each distribution. This requires trying every combination which becomes exponentially expensive.
Greedy with Priority Queue
⏱️ Time: O(extraStudents × log n)
Space: O(n)
Use a max-heap to track which class would benefit most from adding one student. The improvement is calculated as the difference in pass ratio before and after adding a student. Always pick the class with maximum improvement.
Algorithm Steps — Algorithm Steps
Code -
solution.c — C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
double improvement;
int passed;
int total;
} ClassInfo;
static ClassInfo heap[100005];
static int heapSize = 0;
double calculateImprovement(int passed, int total) {
return (double)(passed + 1) / (total + 1) - (double)passed / total;
}
void heapifyUp(int index) {
int parent = (index - 1) / 2;
if (parent >= 0 && heap[parent].improvement < heap[index].improvement) {
ClassInfo temp = heap[parent];
heap[parent] = heap[index];
heap[index] = temp;
heapifyUp(parent);
}
}
void heapifyDown(int index) {
int leftChild = 2 * index + 1;
int rightChild = 2 * index + 2;
int largest = index;
if (leftChild < heapSize && heap[leftChild].improvement > heap[largest].improvement) {
largest = leftChild;
}
if (rightChild < heapSize && heap[rightChild].improvement > heap[largest].improvement) {
largest = rightChild;
}
if (largest != index) {
ClassInfo temp = heap[index];
heap[index] = heap[largest];
heap[largest] = temp;
heapifyDown(largest);
}
}
void heapPush(double improvement, int passed, int total) {
heap[heapSize].improvement = improvement;
heap[heapSize].passed = passed;
heap[heapSize].total = total;
heapifyUp(heapSize);
heapSize++;
}
ClassInfo heapPop() {
ClassInfo result = heap[0];
heapSize--;
if (heapSize > 0) {
heap[0] = heap[heapSize];
heapifyDown(0);
}
return result;
}
double solution(int classes[][2], int numClasses, int extraStudents) {
heapSize = 0;
for (int i = 0; i < numClasses; i++) {
int passed = classes[i][0];
int total = classes[i][1];
heapPush(calculateImprovement(passed, total), passed, total);
}
for (int i = 0; i < extraStudents; i++) {
ClassInfo info = heapPop();
int newPassed = info.passed + 1;
int newTotal = info.total + 1;
heapPush(calculateImprovement(newPassed, newTotal), newPassed, newTotal);
}
double totalRatio = 0;
for (int i = 0; i < heapSize; i++) {
totalRatio += (double)heap[i].passed / heap[i].total;
}
return totalRatio / numClasses;
}
int main() {
char line1[10001], line2[101];
fgets(line1, sizeof(line1), stdin);
fgets(line2, sizeof(line2), stdin);
line1[strcspn(line1, "\n")] = 0;
line2[strcspn(line2, "\n")] = 0;
// Parse classes array
int classes[1000][2];
int numClasses = 0;
char* ptr = line1 + 1; // Skip first __PLACEHOLDER_3__
while (*ptr && *ptr != ']') {
if (*ptr == '[') {
ptr++; // Skip __PLACEHOLDER_6__
int passed = (int)strtol(ptr, &ptr, 10);
ptr++; // Skip __PLACEHOLDER_7__
int total = (int)strtol(ptr, &ptr, 10);
ptr++; // Skip __PLACEHOLDER_8__
classes[numClasses][0] = passed;
classes[numClasses][1] = total;
numClasses++;
if (*ptr == ',') ptr++; // Skip comma between arrays
} else {
ptr++;
}
}
int extraStudents = (int)strtol(line2, NULL, 10);
double result = solution(classes, numClasses, extraStudents);
printf("%.16g\n", result);
return 0;
}
Time & Space Complexity
Time Complexity
⏱️
n
2n
✓ Linear Growth
Space Complexity
n
2n
✓ Linear Space
18.5K Views
MediumFrequency
~25 minAvg. Time
892 Likes
Ln 1, Col 1
Smart Actions
💡Explanation
AI Ready
💡 SuggestionTabto acceptEscto dismiss
// Output will appear here after running code
Code Editor Closed
Click the red button to reopen
Algorithm Visualization
Pinch to zoom • Tap outside to close
Test Cases
0 passed
0 failed
3 pending
Select Compiler
Choose a programming language
Compiler list would appear here...
AI Editor Features
Header Buttons
💡
Explain
Get a detailed explanation of your code. Select specific code or analyze the entire file. Understand algorithms, logic flow, and complexity.
🔧
Fix
Automatically detect and fix issues in your code. Finds bugs, syntax errors, and common mistakes. Shows you what was fixed.
💡
Suggest
Get improvement suggestions for your code. Best practices, performance tips, and code quality recommendations.
💬
Ask AI
Open an AI chat assistant to ask any coding questions. Have a conversation about your code, get help with debugging, or learn new concepts.
Smart Actions (Slash Commands)
🔧
/fix Enter
Find and fix issues in your code. Detects common problems and applies automatic fixes.
💡
/explain Enter
Get a detailed explanation of what your code does, including time/space complexity analysis.
🧪
/tests Enter
Automatically generate unit tests for your code. Creates comprehensive test cases.
📝
/docs Enter
Generate documentation for your code. Creates docstrings, JSDoc comments, and type hints.
⚡
/optimize Enter
Get performance optimization suggestions. Improve speed and reduce memory usage.
AI Code Completion (Copilot-style)
👻
Ghost Text Suggestions
As you type, AI suggests code completions shown in gray text. Works with keywords like def, for, if, etc.
Tabto acceptEscto dismiss
💬
Comment-to-Code
Write a comment describing what you want, and AI generates the code. Try: # two sum, # binary search, # fibonacci
💡
Pro Tip: Select specific code before using Explain, Fix, or Smart Actions to analyze only that portion. Otherwise, the entire file will be analyzed.