表达式生成问题

本文详细解析了四则运算下不同值的生成方法及表达式生成技巧,包括利用深度优先搜索解决不同值问题,递归分治法解决表达式生成问题,以及通过DFS实现特定目标值的表达式构造。同时,介绍了基于分治法的表达式生成过程,以及添加操作符使表达式等于给定目标值的算法。

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

如何划分:表达式是一步一步算的,划分的方法就是哪个数先加入和表达式的当前值进行计算,并且有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

为了帮助你高效掌握字节跳动研发笔试题中的社交网络分组和合法表达式成问题,建议参阅《字节跳动研发笔试题解析:团队分组与合法表达式问题》。这本书详细解析了历年字节跳动研发笔试题目的解题思路和方法,对于准备面试和提升编程能力的开发者来说,是不可多得的学习资源。 参考资源链接:[字节跳动研发笔试题解析:团队分组与合法表达式问题](https://wenku.csdn.net/doc/5szttbwiwy) 针对社交网络分组问题,建议采用并查集数据结构。并查集可以高效地合并和查询集合,适合处理图中的连通分量问题。具体实现时,可以先初始化每个节点为独立的集合,然后遍历所有边,对于每条边,找到两个节点所在的集合,并将这两个集合合并。最后统计不同集合的数量即为最少的分组数。这种方法在时间复杂度上优于DFS,更适合处理大规模数据。 对于合法表达式成问题,可以使用动态规划来解决问题。动态规划是一种通过把原问题分解为相对简单的子问题的方式来求解复杂问题的方法。在实现时,可以创建一个数组dp来存储每个长度的合法表达式的数量,按照状态转移方程计算出结果。记得在每次计算过程中对结果取模,以避免整数溢出。 在掌握这些解题策略之后,可以通过模拟面试的方式进行实战演练,不断优化代码的效率和可读性。通过上述的学习和练习,你将能更加自信地面对字节跳动研发岗位的笔试挑战。如果你想进一步提升算法能力,可以参考更多高级编程挑战资源,如《算法导论》和在线编程平台如LeetCode的高级题库,它们将为你提供更多类型的问题和解决方案。 参考资源链接:[字节跳动研发笔试题解析:团队分组与合法表达式问题](https://wenku.csdn.net/doc/5szttbwiwy)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值