คำอธิบายปัญหา
ให้จำนวนเต็มบวก x เขียนนิพจน์รูป x op1 x op2 x op3 ... โดย op ∈ {+,-,*,/} กฎ:
- / คืนค่าจำนวนตรรกยะ (ไม่ใช่ integer division)
- ไม่มีวงเล็บ
- ลำดับการดำเนินการปกติ: */ ก่อน +-
- ห้ามใช้ unary negation
หาจำนวนตัวดำเนินการน้อยที่สุดเพื่อให้นิพจน์มีค่าเท่ากับ target
ตัวอย่าง
x = 4, target = 15 → Output: 3
นิพจน์: 4*4 - 4/4 = 16 - 1 = 15 (3 ตัวดำเนินการ)
แนวทางแก้ปัญหา: Recursive + Greedy
- กรณีฐาน: target == x → 0 ตัวดำเนินการ
- ถ้า x > target: min((x-target)*2, target*2-1)
- x-target: ใช้การลบ (x/x + x/x + ...)
- target: ใช้การบวก (x/x + x/x + ...)
- หา sum = xᵗ ใกล้ target มากที่สุด (sum ≥ target)
- ถ้า sum == target → คืน t
- พิจารณา 2 ทางเลือก:
- l: ใช้ sum/x เป็นฐาน แล้วบวก (target - sum/x) → cost = leastOps(x, target - sum/x) + t - 1
- r: ใช้ sum เป็นฐาน แล้วลบ (sum - target) → cost = leastOps(x, sum - target) + t (ถ้า sum-target < target)
- คืน 1 + min(l, r) (บวก 1 สำหรับ * หรือ / ที่เชื่อม)
ตัวอย่างโค้ด C++
#include <bits/stdc++.h>
using namespace std;
typedef long long lli;
class Solution {
public:
int leastOpsExpressTarget(int x, int target) {
if(target == x) return 0;
if(x > target) {
return min((x-target)*2, target*2-1);
}
lli sum = x;
int t = 0;
while(sum < target) { sum *= x; t++; }
if(sum == target) return t;
int l = INT_MAX, r = INT_MAX;
if(sum - target < target)
r = leastOpsExpressTarget(x, sum - target) + t;
l = leastOpsExpressTarget(x, target - sum/x) + t - 1;
return min(l, r) + 1;
}
};
ความซับซ้อน
- เวลา: O(logₓ target) เนื่องจากลดปัญหาลงเรื่อยๆ
- พื้นที่: O(logₓ target) สำหรับ recursion stack