188 lines
4.8 KiB
C#
188 lines
4.8 KiB
C#
// LeetCode 1792: Maximum Average Pass Ratio
|
|
// 難度: Medium
|
|
// 日期: 2025-09-01
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
|
|
public class Solution
|
|
{
|
|
public double MaxAverageRatio(int[][] classes, int extraStudents)
|
|
{
|
|
// use priority queue
|
|
var pq = new PriorityQueue<ClassInfo, double>();
|
|
|
|
// 初始化:將所有班級加入優先佇列
|
|
for (int i = 0; i < classes.Length; i++)
|
|
{
|
|
int pass = classes[i][0];
|
|
int total = classes[i][1];
|
|
|
|
double gain = CalculateGain(pass, total);
|
|
|
|
pq.Enqueue(new ClassInfo(pass, total), -gain);
|
|
}
|
|
|
|
for (int i = 0; i < extraStudents; i++)
|
|
{
|
|
var classInfo = pq.Dequeue();
|
|
|
|
classInfo.Pass++;
|
|
classInfo.Total++;
|
|
|
|
double newGain = CalculateGain(classInfo.Pass, classInfo.Total);
|
|
pq.Enqueue(classInfo, -newGain);
|
|
}
|
|
|
|
double totalRatio = 0;
|
|
while (pq.Count > 0)
|
|
{
|
|
var classInfo = pq.Dequeue();
|
|
totalRatio += (double)classInfo.Pass / classInfo.Total;
|
|
}
|
|
|
|
return totalRatio / classes.Length;
|
|
}
|
|
|
|
public double MaxAverageRatioByBruteForce(int[][] classes, int extraStudents)
|
|
{
|
|
var n = classes.Length;
|
|
var pass = new int[n];
|
|
var total = new int[n];
|
|
|
|
for (var i = 0; i < n; i++)
|
|
{
|
|
pass[i] = classes[i][0];
|
|
total[i] = classes[i][1];
|
|
}
|
|
|
|
for (int student = 0; student < extraStudents; student++)
|
|
{
|
|
int bestClass = -1;
|
|
double maxInprovement = 0;
|
|
|
|
for (int i = 0; i < n; i++)
|
|
{
|
|
double currentAvg = CalculateAvergaeRatio(pass, total);
|
|
|
|
pass[i]++;
|
|
total[i]++;
|
|
|
|
double newAvg = CalculateAvergaeRatio(pass, total);
|
|
double improvement = newAvg - currentAvg;
|
|
|
|
pass[i]--;
|
|
total[i]--;
|
|
|
|
if (improvement > maxInprovement)
|
|
{
|
|
maxInprovement = improvement;
|
|
bestClass = i;
|
|
}
|
|
}
|
|
|
|
if (bestClass != -1)
|
|
{
|
|
pass[bestClass]++;
|
|
total[bestClass]++;
|
|
}
|
|
}
|
|
|
|
return CalculateAvergaeRatio(pass, total);
|
|
}
|
|
|
|
private double CalculateGain(int pass, int total)
|
|
{
|
|
// 計算提升率
|
|
return (double)(pass + 1) / (total + 1) - (double)pass / total;
|
|
}
|
|
|
|
private double CalculateAvergaeRatio(int[] pass, int[] total)
|
|
{
|
|
double sum = 0;
|
|
for (var i = 0; i < pass.Length; i++)
|
|
{
|
|
sum += (double)pass[i] / total[i];
|
|
}
|
|
return sum / pass.Length;
|
|
}
|
|
}
|
|
|
|
public class ClassInfo
|
|
{
|
|
public int Pass { get; set; }
|
|
public int Total { get; set; }
|
|
|
|
public ClassInfo(int pass, int total)
|
|
{
|
|
Pass = pass;
|
|
Total = total;
|
|
}
|
|
}
|
|
|
|
// 測試程式
|
|
public class Program
|
|
{
|
|
public static void Main()
|
|
{
|
|
Solution solution = new Solution();
|
|
|
|
// TestCase
|
|
TestCase1(solution);
|
|
TestCase2(solution);
|
|
}
|
|
|
|
static void TestCase1(Solution solution)
|
|
{
|
|
// Input:
|
|
int[][] classes = new int[][]
|
|
{
|
|
new int[] {1, 2},
|
|
new int[] {3, 5},
|
|
new int[] {2, 2}
|
|
};
|
|
int extraStudents = 2;
|
|
|
|
Console.WriteLine("Test 1: ");
|
|
Console.WriteLine($"classes: [{string.Join("], [", classes.Select(c => string.Join(", ", c)))}]");
|
|
Console.WriteLine($"extraStudents: {extraStudents}");
|
|
|
|
// Expected:
|
|
Console.WriteLine("Expect: ");
|
|
Console.WriteLine($"output: 0.78333");
|
|
|
|
// Actual:
|
|
Console.WriteLine("Actual: ");
|
|
Console.WriteLine($"Brute Force: {solution.MaxAverageRatioByBruteForce(classes, extraStudents):F6}");
|
|
Console.WriteLine($"Priority Queue: {solution.MaxAverageRatio(classes, extraStudents):F6}");
|
|
}
|
|
|
|
|
|
static void TestCase2(Solution solution)
|
|
{
|
|
// Input:
|
|
int[][] classes = new int[][]
|
|
{
|
|
new int[] {2, 4},
|
|
new int[] {3, 9},
|
|
new int[] {4, 5},
|
|
new int[] {2, 10}
|
|
};
|
|
int extraStudents = 4;
|
|
|
|
Console.WriteLine("Test 2: ");
|
|
Console.WriteLine($"classes: [{string.Join("], [", classes.Select(c => string.Join(", ", c)))}]");
|
|
Console.WriteLine($"extraStudents: {extraStudents}");
|
|
|
|
// Expected:
|
|
Console.WriteLine("Expect: ");
|
|
Console.WriteLine($"output: 0.53485");
|
|
|
|
// Actual:
|
|
Console.WriteLine("Actual: ");
|
|
Console.WriteLine($"Brute Force: {solution.MaxAverageRatioByBruteForce(classes, extraStudents):F6}");
|
|
Console.WriteLine($"Priority Queue: {solution.MaxAverageRatio(classes, extraStudents):F6}");
|
|
}
|
|
}
|