假设我们有x个数字和x-1个运算符(+或-)的序列,其中数字和运算符的顺序是固定的。例如5-2-1 + 3。通过不同的括号可以得到不同的值。例如(5-2)-1 + 3 = 5,5-(2-1)+ 3 = 7,依此类推。我现在对线性运行时/内存空间的最大和最大感兴趣。
我认为可以通过动态编程解决此问题,但是我根本没有找到有意义的变体。
答案 0 :(得分:0)
您这里需要的当然是动态算法。 这将以递归的方式工作,找到每个范围可以获取的最大值。
算法:
您可以将数字和运算符分隔到不同的列表中(如果第一个数字为正数,请首先在列表中添加+
。
max_sum(expression, operators):
if len(expression) == 1: return expression
max_value = -float('inf') # minus infinity
length = len(expression)
for i in range(length):
left_exp = max_sum(expression[0:i], operators[0:i])
right_exp = max_sum(expression[i:length], operators[i:length])
value = operator[i].apply(left_exp, right_exp)
if value >= max_value:
max_value = value
return max_value
该算法的主要思想是,它会检查每个可能的范围划分中的最大和,然后递归向下进行计算,然后返回得到的最大和。
伪代码没有考虑通过减去正确表达式的最小值可以得到最大值的情况,但是我想通过一些调整就可以很快解决它。
我试图使伪代码尽可能容易地转换为代码,希望对您有所帮助。
答案 1 :(得分:0)
让表达式是一个由运算符-数字对组成的序列:它以一个运算符开头,后跟一个数字,然后以一个运算符后面加一个数字结束。通过将5-2-1+3
放在开头+
,可以使示例+5-2-1+3
成为表达式。
让表达式的头部成为其第一个运算符数字对,其尾部成为其余。 +5-2-1+3
的头是+5
,尾巴是-2-1+3
。
在这种情况下,让表达式带有括号意味着在第一个运算符之后放置一个左括号,在表达式的末尾放置一个右括号,例如:+(5-2-1+3)
。用正括号将表达式括起来并没有任何作用。用负号括起来的表达式等效于更改其尾部的每个符号:-(5 -2-1+3) = -5 +2+1-3
。
如果您想通过将某些子表达式括起来来获得极值,则可以先进行一些简化。很容易看出,+x1+x2+...+xn
形式的任何子表达式都不会被拆分:其所有元素都将一起用于极值。同样,任何形式为-x1-x2-...-xn
的子表达式都不会被拆分,但是可以用括号括起来(-(x1-x2-...-xn)
)。因此,您可以先将第一种形式的任何子表达式简化为+X
,其中X
是其元素的总和,然后将第二种形式的任何子表达式简化为-x1-X
,其中{{1 }}是其尾元素的总和。
结果表达式不能具有3个连续的X
运算符或2个连续的-
运算符。现在,从头开始,找到格式为+
,-a-b
或-a+b-c
的第一个子表达式,然后计算其潜在最小值和潜在最大值:
-a+b
min(-a-b) = -a-b
max(-a-b) = -(a-b)
min(-a+b-c) = -(a+b)-c
max(-a+b-c) = -a+b-c if b>=c, max(-a+b-c) = -(a+b-c) if b<=c
min(-a+b) = -(a+b)
通过将该子表达式作为下一个表达式中的单个运算符-数字对来进行重复,尽管有两个可能的值(两个极值)。这样,将计算每个后续子表达式的极值,直到到达主表达式为止,您可以简单地计算出最大值。请注意,主表达式可能有一个正的第一对,这使它成为特例,但这很容易考虑:只需将其添加到最大值即可。