โจทย์
เครื่องคิดเลขเสีย มี 2 ปุ่ม:
- Double: คูณ 2
- Decrement: ลด 1
เริ่มที่ X ต้องการไป Y หา operations น้อยที่สุด
ตัวอย่าง: X=5, Y=8 → 2 ops: 5→4 (dec), 4→8 (double)
ข้อสังเกตสำคัญ: ย้อนกลับ (Reverse Thinking)
แทนที่จะคิด X→Y (branch factor 2) ให้คิด Y→X (branch factor 1 หรือ 2):
- ถ้า Y เป็นเลขคู่: ย้อน Double ได้ → Y = Y/2
- ถ้า Y เป็นเลขคี่: ย้อน Double ไม่ได้ ต้องย้อน Decrement → Y = Y+1
- ทำซ้ำจน Y ≤ X
- Operations ที่เหลือ = X - Y (แค่ Decrement)
การติดตั้ง (Python Implementation)
class Solution:
def brokenCalc(self, X: int, Y: int) -> int:
ops = 0
while Y > X:
if Y % 2 == 0:
Y //= 2
else:
Y += 1
ops += 1
return ops + (X - Y)
# ทดสอบ
ob = Solution()
print(ob.brokenCalc(5, 8)) # 2
print(ob.brokenCalc(3, 10)) # 3 (3→6→5→10)
print(ob.brokenCalc(10, 1)) # 9 (แค่ decrement)
print(ob.brokenCalc(1, 1000000000)) # Large test
Output
2 3 9 ... (คำตอบสำหรับ large test)
การวิเคราะห์ตัวอย่าง X=5, Y=8
Y=8 > 5, even → Y=4, ops=1 Y=4 ≤ 5, stop Remaining: X-Y = 5-4 = 1 Total: 1 + 1 = 2 ops Path: 5 → 4 (dec) → 8 (double)
ทำไม Reverse Greedy ถูกต้อง?
- Double (×2) เป็น operation "รุนแรง" เปลี่ยนค่ามาก → ควรทำทีหลัง (forward) / ทีแรก (reverse)
- Decrement (±1) เป็น operation "อ่อน" → ทำทีหลัง (forward) / ทีหลัง (reverse)
- Reverse greedy เลือกการย้อน Double ทุกครั้งที่ทำได้ (Y even) ซึ่งเป็น optimal
Complexity
- Time: O(log Y) - Y ลดลงครึ่งหนึ่งทุก 1-2 steps
- Space: O(1)
สรุป
Broken Calculator เป็นโจทย์ Greytic แบบ Reverse Thinking: คิดย้อนกลับจาก Y ไป X ใช้ parity ของ Y 决定 operation ย้อนกลับ เร็วและ optimal
หากมีข้อสงสัย สามารถถามได้ในส่วนความคิดเห็นครับ