Given a single positive integer x
, we will write an expression of the form x (op1) x (op2) x (op3) x ...
where each operator op1
, op2
, etc. is either addition, subtraction, multiplication, or division (+
, -
, *
, or /)
. For example, with x = 3
, we might write 3 * 3 / 3 + 3 - 3
which is a value of 3.
When writing such an expression, we adhere to the following conventions:
- The division operator (
/
) returns rational numbers. - There are no parentheses placed anywhere.
- We use the usual order of operations: multiplication and division happens before addition and subtraction.
- It's not allowed to use the unary negation operator (
-
). For example, "x - x
" is a valid expression as it only uses subtraction, but "-x + x
" is not because it uses negation.
We would like to write an expression with the least number of operators such that the expression equals the given target
. Return the least number of operators used.
Example 1:
Input: x = 3, target = 19
Output: 5
Explanation: 3 * 3 + 3 * 3 + 3 / 3. The expression contains 5 operations.
Example 2:
Input: x = 5, target = 501
Output: 8
Explanation: 5 * 5 * 5 * 5 - 5 * 5 * 5 + 5 / 5. The expression contains 8 operations.
Example 3:
Input: x = 100, target = 100000000
Output: 3
Explanation: 100 * 100 * 100 * 100. The expression contains 3 operations.
Note:
2 <= x <= 100
1 <= target <= 2 * 10^8
這道題說是給了一個正整數x,我們需要讓x通過一些運算組成另一個正整數 target,這里的x可以不限次數使用,運算只包括加減乘除,不帶括號,但需要滿足乘除優先的基本規律。並且這里的除法是整數除法,減號不能當作負數符號使用,讓我們求要組成 target 的最少的運算符的使用個數。雖然題目很長不好理解,但是通過例子還是不難理解題意的,難就難在如何解題。博主看了一會兒,發現沒思路就直接放棄了,直奔論壇上找解法。這里直接參考 donggua_fu
大神的解法吧,首先處理 edge cases,當 x 等於 target 的話,不用加任何運算符,返回0即可。若 x 大於 target,比如 x=5,target=3,我們其實可以迅速的求出運算符的個數,因為5比3大,要湊3就只能先變成1,這里就有兩種變法,一種是全部都變成1,然后來湊3,即 5/5 + 5/5 + 5/5
,這時的運算符個數是 target * 2 -1
,因為加號的個數總是比除號少一個。另一種湊法就是 5 - 5/5 - 5/5
,這時候的運算符個數是 (x - target) * 2
,此時的加號和除號的個數相同,均為x和 target 的差值。
接下來就要處理 x 小於 target 的情況了,此時由於不知道x到底比 target 小多少,若差距太大的話,肯定不能用加號,所以應該先用乘號來讓x變大,直到剛好大於等於 target 停止,並每次增加次數 cnt。若此時 sum 正好等於 target,太幸運了,直接返回 cnt。但通常情況下 sum 會大於 target,此時 sum - target
的差值就需要另行計算了。這里差值跟 target 的大小關系又要分為兩種情況來討論,當 sum - target < target
時,比如 x=5,sum=25,target=15,則 sum - target=10,就是說現在已經乘到了 25,但需要再減去 10,這個差值 10 可以再次調用原函數來計算,此時新的 target 代入 10 即可,記得返回值要加上 cnt。當然之后還是要再計算一下另一種湊的方法,由於 sum 超過了 target,所以回退一個x,變成 sum / x
,此時小於 target,那么它們的差值 target - (sum / x)
就可以通過再次調用函數來計算,注意這里加上 cnt 之后還要減去1,因為回退了一個x,少了一個乘號。最終二者的較小值即為所求,記得要加上個1,以為多加了個運算符,參見代碼如下:
class Solution {
public:
int leastOpsExpressTarget(int x, int target) {
if (x == target) return 0;
if (x > target) {
return min(target * 2 - 1, (x - target) * 2);
}
long sum = x;
int cnt = 0;
while (sum < target) {
sum *= x;
++cnt;
}
if (sum == target) return cnt;
int res1 = INT_MAX, res2 = INT_MAX;
if (sum - target < target) {
res1 = leastOpsExpressTarget(x, sum - target) + cnt;
}
res2 = leastOpsExpressTarget(x, target - (sum / x)) + cnt - 1;
return min(res1, res2) + 1;
}
};
Github 同步地址:
https://github.com/grandyang/leetcode/issues/964
參考資料:
https://leetcode.com/problems/least-operators-to-express-number/