表达式生成问题

12 篇文章 0 订阅
6 篇文章 0 订阅

题目:给定一个数组,问:这组数进行四则运算(每个数必须用到,且只用一次)可以得到多少个不同的值?

如何划分:表达式是一步一步算的,划分的方法就是哪个数先加入和表达式的当前值进行计算,并且有4种计算方式(其实是6种,减法和除法各2种顺序)

def uniqueValues(A):
	ans = set()
	def dfs(i, value):
		if i == len(A): ans.add(value)
		else:
			for j in xrange(i, len(A)):
				A[i], A[j] = A[j], A[i]
				if i == 0:
					dfs(i + 1, value + A[i])
				else:
					dfs(i + 1, value + A[i])
					dfs(i + 1, value - A[i])
					dfs(i + 1, A[i] - value)
					dfs(i + 1, value * A[i])
					dfs(i + 1, value / A[i])
					if value != 0: dfs(i + 1, A[i] / value)
				A[i], A[j] = A[j], A[i]
	dfs(0, 0)
	return ans

题目2,给定一个数的集合,打印所有可以生成的不同表达式

划分:以最后进行的计算作为划分,是一个不相交且完备的划分。分治法,以最后进行的计算为轴,把集合分成2组,递归求解两边边的集合,然后组合最后的表达式集合。

cache = {}
def expressions(A):
    if len(A) == 1: return [str(A[0])]
    else:
        A.sort()
        key = tuple(A)
        if key in cache.keys(): return cache[key]
        left, right, ans = [], [], []
        def group(i, leftCount, rightCount):
            if i == len(A):
                for exp1 in expressions(left):
                    for exp2 in expressions(right):
                        exp1 = exp1 if exp1.isdigit() or exp1[0] == '(' else '(' + exp1 + ')'
                        exp2 = exp2 if exp2.isdigit() or exp2[0] == '(' else '(' + exp2 + ')'
                        for op in '+-*/': ans.append(exp1 + op + exp2)
                        ans.append(exp2 + '-' + exp1)
                        ans.append(exp2 + '/' + exp1)
            else:
                if leftCount < len(A) - 1:
                    left.append(A[i])
                    group(i + 1, leftCount + 1, rightCount)
                    left.pop()
                if leftCount == 0: return
                if rightCount < len(A) - 1:
                    right.append(A[i])
                    group(i + 1, leftCount, rightCount + 1)
                    right.pop()
        group(0, 0, 0)
        cache[tuple(A)] = ans
        return ans


做法2:不需要存储,一般dfs,但是有重复,是正确结果的2倍

def expressions(A, i, exp):
    if len(A) == i: print exp
    else:
        for j in xrange(i, len(A)):
            A[i], A[j] = A[j], A[i]
            if i == 0: expressions(A, i + 1, str(A[i]))
            else:
                for op in '+-*/': expressions(A, i + 1, '(' + exp + op + str(A[i]) +')')
                expressions(A, i + 1, '(' + str(A[i]) + '-' + exp + ')')
                expressions(A, i + 1, '(' + str(A[i]) + '/' + exp + ')')
            A[i], A[j] = A[j], A[i]

题目3 给定一组数,添加操作符使得表达式值为给定target(类似的问法:添加操作符使得等式成立)

把表达式看做是term的和,term由factor组成。t是表达式最后一个term,

def solve(A, i, v, t, target, e):
    if i == len(A):
        if v == target: print e
    else:
        if i == 0: solve(A, i + 1, A[i], A[i], target, str(A[i]))
        else:
            solve(A, i + 1, v + A[i], A[i], target, e + '+' + str(A[i]))
            solve(A, i + 1, v - A[i], -A[i], target, e + '-' + str(A[i]))
            solve(A, i + 1, v - t + t * A[i], t * A[i], target, e + '*' + str(A[i]))
            if A[i] != 0: solve(A, i + 1, v - t + t / A[i], t / A[i], target, e + '/' + str(A[i]))

题目4 给定一组数,打印可以构造的所有表达式,数的顺序不能变,和题目2类似,差别就是顺序不能变

def all_exp(A, l, r):
    if l == r: yield str(A[l])
    else:
        for pivot in xrange(l, r):
            for left in all_exp(A, l, pivot):
                for  right in all_exp(A, pivot + 1, r):
                    for op in '+-*/':
                        yield '(' + left + op + right + ')'

分治法一般需要保存子问题的结果,这里用generaor

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值