282. 给表达式添加运算符
难度:困难
问题描述:
给定一个仅包含数字 0-9 的字符串 num 和一个目标值整数 target ,
在 num 的数字之间添加 二元 运算符(不是一元)+、- 或 * ,返回
所有 能够得到 target 的表达式。
注意,返回表达式中的操作数 不应该 包含前导零。
示例 1:
输入: num = "123", target = 6
输出: ["1+2+3", "1*2*3"]
解释: “1*2*3” 和 “1+2+3” 的值都是6。
示例 2:
输入: num = "232", target = 8
输出: ["2*3+2", "2+3*2"]
解释: “2*3+2” 和 “2+3*2” 的值都是8。
示例 3:
输入: num = "3456237490", target = 9191
输出: []
解释: 表达式 “3456237490” 无法得到 9191 。
'''
分析:
枚举算法是一种利用循环结构不断地进行列举和检验,从而完成问题求解的算法。
本问题解决的关键是找到num各个数字之间要插入的运算符共有多少种排列组合,然后利用枚举法列举出num各个数字和运算符组成的表达式,检验该表达式运算结果是否等于target,如果等于,则是一种符合条件的表达式,否则继续列举,直到所有的组合列举完成。
处理问题一共设计两个函数:
- pl取排列的意思,pl(n)函数用于生成每个位置有三种运算符“+-*”可选,n个位置共组成多少个运算符的排列组合
- cl取处理的意思,cl(num,target)函数先根据num中有多少个数字,得到应该插入多少个运算符,插入运算符的个数等于num中数字个数减1,进而生成运算符的排列组合列表,然后用num中的数字和运算符列表依次生成表达式,检验其运算结果是否等于target,最后将满足条件的表达式添加进列表,并作为结果返回。
程序如下:
#pl(n)函数用于处理每个位置有'+-*'三种运算符可以选择,
#n个位置共有多少种排列组合的问题,并返回运算符排列列表
def pl(n):
if n==1:
return ['+','-','*']
else:
b=[]
for i in '+-*':
for j in pl(n-1):
b.append(i+j)
return b
#根据num和target的值,列举各种可能的运算符组合,检验能够得到target的表达式
def cl(num,target):
n=len(num)-1 #两个字符中间只能插入一个运算符,n个字符之间只能插入n-1个运算符
a=pl(n)
c=[]
for i in a:
s=num[0]
b=list(zip(list(i),list(num[1:])))
for j in b:
s=s+j[0]+j[1]
if eval(s)==target:
c.append(s)
return c
#输入
num=input('pls input num=')
target=int(input('pls input target='))
#调用函数并输出结果
myanswer=cl(num,target)
print(myanswer)
运行实例1:
pls input num=234578
pls input target=27
['2*3+4*5-7+8']
运行实例2:
pls input num=232
pls input target=8
['2+3*2', '2*3+2']
运行实例3:
pls input num=23456
pls input target=25
['2+3*4+5+6', '2-3+4*5+6', '2-3-4+5*6', '2*3*4-5+6']
运行实例4:
pls input num=3456
pls input target=15
[]
感悟:
枚举算法虽然从原理上来说是一种笨办法,但它恰恰利用了计算机不怕繁杂,不怕机械枯燥重复,更不会有怨言的特点,是一种解决问题非常实用的方法。