您的位置:首页 > 编程语言 > Python开发

python算法习题(四): 添加运算符

2018-04-04 17:33 323 查看

1. 题目

给定一个仅包含数字 0 - 9 的字符串和一个目标值,返回在数字之间添加了 二元 运算符(不是一元)+, - 或 * 之后所有能得到目标值的情况。

样例:

“123”, 6 -> [“1+2+3”, “1*2*3”]

“232”, 8 -> [“2*3+2”, “2+3*2”]

“105”, 5 -> [“1*0+5”,”10-5”]

“00”, 0 -> [“0+0”, “0-0”, “0*0”]

“3456237490”, 9191 -> []

2. 思路

没想到更好的办法,只能枚举。然而枚举也并不是想象中的那么简单。可能是方式不对,希望有大神指教。总的思路是插入法,在数字中插入所有可能的操作符号排序。然后字符串化,利用内置函数eval求值判断是否与期望值相等。

3. 代码

def gen_operator(d):   # 生成对应个数的操作符号组合列表
res = []
choice = ['+', '-', '*']
t = [0]*d
def loop(t, n):
if n == d:
c = t.copy()   # 可变
res.append(c)
else:
for i in choice:
t
= i
loop(t, n+1)
loop(t, 0)
return res

from itertools import combinations   # 这里使用内置函数,不再重复造轮子
import re

def addOperators(nums, target):
res = []

ex_nums = [' ']*(len(nums)*2-1)  # 输入数字字符串扩展成列表。例如:['1', ' ', '2', ' ', '3']
space_index = []
for index, i in enumerate(nums):
ex_nums[2*index] = i
space_index.append(2*index+1)
space_index.pop()  # 得到对应的下标列表。例如:[1, 3]

for i in range(1, len(space_index)+1):
"""数字分割方式。例如:可以选下标1插入一个操作符(1?23),也可也选择下标3插入一个操作符(12?3),
或者选择下标1和3插入两个操作符(1?2?3)。所以有i种情况。"""
index_comb = combinations(space_index, i)  # 得到i个分割操作符的所有组合
for index_tuple in index_comb:
for operator_list in gen_operator(i):  # 生成i个操作符号的组合
tmp = ex_nums.copy()               # 复制不改变原始列表
for operator, index in zip(operator_list, index_tuple):
tmp[index] = operator      # 对应下标赋值
setence = ''.join(["%s" % a for a in tmp if a != ' ']) # 生成字符串
# 去掉‘1+05’这种操作符后面跟‘0’的情况,否则eval函数报错
setence = re.sub(r'[\+\-\*]0+[1-9]+', lambda m: m.group().replace('0', ''), setence)
if eval(setence) == target:  # eval转化成有效表达式求值并判断
res.append(setence)
return res

print(addOperators('123', 6))
print(addOperators('105', 5))
print(addOperators('00', 0))
结果:
['1+2+3', '1*2*3']
['1*5', '10-5', '1*0+5']  # 这里答案可能与标准答案不一样,因为这里认为‘1*05’等价于‘1*5’
['0+0', '0-0', '0*0']


4. 总结

整体上代码完成了要求的功能,但是没有进行异常情况的考虑。re模块替换功能还可以用函数,好厉害!

之前有次笔试,好不容易把最后一道试题做对,那个HW离职出来工作的面试官一个劲地强调我们这个主要是考异常分析算法不重要。还说这个题目华为用了多少年有多少种异常要考虑。好气啊。。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息