【Leetcode】964. Least Operators to Express Number 表示数字的最少运算符

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:

  1. 2 <= x <= 100
  2. 1 <= target <= 2 * 10^8

解法

无语辽,想了3个小时= =
这个就算能想出来也没法在面试的时候想出来……
首先要注意审题,没有括号意味着:

  1. 最后结果一定是x的i次方相加减(i>=0)
  2. 由于target是整数所以不可能有i<0

这样的话我们第一反应就是把target转换成x进制,得到:
target = ∑ i a i x i \text{target} = \sum_ia_ix^i target=iaixi
首先需要注意,组合 x i x^i xi需要 m m m个运算符,m = i==0?1:i-1
我们需要组合出每个 a i a_i ai不为0的 a i x i a_ix^i aixi,这有两种方法:

  1. a i a_i ai x i x^i xi相加,这时第i位需要的运算符为 a i ∗ ( m + 1 ) a_i*(m+1) ai(m+1)
  2. 借一个高位过来,用一个 x i + 1 x^{i+1} xi+1减去 x − a i x-a_i xai x i x^i xi,这样第i位需要的运算符为 ( x − a i ) ∗ ( m + 1 ) (x-a_i)*(m+1) (xai)(m+1),只不过第i+1位从要组合 a i + 1 x i + 1 a_{i+1}x^{i+1} ai+1xi+1变成了要组合 ( a i + 1 ) x i + 1 (a_{i+1})x^{i+1} (ai+1)xi+1

所以,每一位有两种可能性,一种是要组合 a i a_i ai,另一种是要组合 a i + 1 a_i+1 ai+1,我们令 f [ i ] [ 0 ] f[i][0] f[i][0]表示第i位组合 a i a_i ai时的最小运算符数, f [ i ] [ 1 ] f[i][1] f[i][1]表示第i位组合 a i + 1 a_i+1 ai+1时的最小运算符数。得到状态转移方程
f [ i ] [ 0 ] = min ⁡ { f [ i + 1 ] [ 0 ] + a i ∗ ( m + 1 ) , f [ i + 1 ] [ 1 ] + ( x − a i ) ∗ ( m + 1 ) } f[i][0] = \min\{f[i+1][0]+a_i*(m+1), f[i+1][1]+(x-a_i)*(m+1)\} f[i][0]=min{f[i+1][0]+ai(m+1),f[i+1][1]+(xai)(m+1)}
f [ i ] [ 1 ] = min ⁡ { f [ i + 1 ] [ 0 ] + ( a i + 1 ) ∗ ( m + 1 ) , f [ i + 1 ] [ 1 ] + ( x − a i − 1 ) ∗ ( m + 1 ) } f[i][1] = \min\{f[i+1][0]+(a_i+1)*(m+1), f[i+1][1]+(x-a_i-1)*(m+1)\} f[i][1]=min{f[i+1][0]+(ai+1)(m+1),f[i+1][1]+(xai1)(m+1)}
为了节省空间,可以只用2个变量
代码如下:

class Solution(object):
    def leastOpsExpressTarget(self, x, target):
        """
        :type x: int
        :type target: int
        :rtype: int
        """
        n = int(math.log(target,x))
        mask = x**n
        last = [0,n+1]
        for i in xrange(n,-1,-1):
            d = target//mask
            multis = 2 if i==0 else i
            last = [min(last[1]+(x-d)*multis,last[0]+d*multis), min(last[1]+(x-d-1)*multis,last[0]+(d+1)*multis)]
            target = target % mask
            mask /=x
        return last[0]-1
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值