โจทย์: กำหนดรายการขนาดล็อก logs และขีดจำกัด limit แต่ละ logs[i] คือขนาดล็อกของผู้ใช้ i ต้องการหา ค่า x สูงสุด ที่ถ้าตัดล็อกทุกตัวให้ไม่เกิน x ผลรวมขนาด ≤ limit หากไม่ต้องตัดเลย ให้คืนค่าล็อกสูงสุด
ตัวอย่าง
Input: logs = [500, 200, 10000, 500, 4000], limit = 3000
Output: 900
เหตุผล: ตัดที่ 900 ได้ [500, 200, 900, 500, 900] ผลรวม = 3000
อัลกอริทึม: Binary Search on Answer
ฟังก์ชัน f(x) = sum(min(x, log) for log in logs) เป็นฟังก์ชันไม่ลดลง (Monotonic) → ใช้ Binary Search หา x สูงสุดที่ f(x) ≤ limit
ขั้นตอนการทำงาน
lo = 0, hi = max(logs) + 1- วนลูป
while lo + 1 < hi:mi = lo + (hi - lo) // 2- คำนวณ
total = sum(min(mi, log) for log in logs) - หาก
total <= limit:lo = mi(ลองค่ามากขึ้น) - มิฉะนั้น:
hi = mi(ลองค่าน้อยลง)
- คืนค่า
lo
โค้ด Python
def solve(logs, limit):
lo, hi = 0, max(logs) + 1
while lo + 1 < hi:
mi = lo + (hi - lo) // 2
if sum(min(mi, log) for log in logs) <= limit:
lo = mi
else:
hi = mi
return lo
# ทดสอบ
logs = [500, 200, 10000, 500, 4000]
limit = 3000
print(solve(logs, limit)) # Output: 900
การทำงานทีละขั้นตอน (Trace)
logs = [500, 200, 10000, 500, 4000], limit = 3000
| lo | hi | mi | sum(min(mi, log)) | ≤3000? | action |
|---|---|---|---|---|---|
| 0 | 10001 | 5000 | 500+200+5000+500+4000=10200 | No | hi=5000 |
| 0 | 5000 | 2500 | 500+200+2500+500+2500=6200 | No | hi=2500 |
| 0 | 2500 | 1250 | 500+200+1250+500+1250=3700 | No | hi=1250 |
| 0 | 1250 | 625 | 500+200+625+500+625=2450 | Yes | lo=625 |
| 625 | 1250 | 937 | 500+200+937+500+937=3074 | No | hi=937 |
| 625 | 937 | 781 | 500+200+781+500+781=2762 | Yes | lo=781 |
| 781 | 937 | 859 | 500+200+859+500+859=2918 | Yes | lo=859 |
| 859 | 937 | 898 | 500+200+898+500+898=2996 | Yes | lo=898 |
| 898 | 937 | 917 | 500+200+917+500+917=3034 | No | hi=917 |
| 898 | 917 | 907 | 500+200+907+500+907=3014 | No | hi=907 |
| 898 | 907 | 902 | 500+200+902+500+902=3004 | No | hi=902 |
| 898 | 902 | 900 | 500+200+900+500+900=3000 | Yes | lo=900 |
| 900 | 902 | 901 | 500+200+901+500+901=3002 | No | hi=901 |
จบลูป (lo+1=901 >= hi=901) → คืนค่า 900
ความซับซ้อน
- Time Complexity: O(n log M) โดย M = max(logs)
- Space Complexity: O(1)
กรณีพิเศษ
print(solve([100, 200, 300], 1000)) # 300 (ไม่ต้องตัด ผลรวม 600 ≤ 1000)
print(solve([1000, 2000], 500)) # 250 (ตัดทั้งคู่)
print(solve([], 100)) # 0 (empty list)