所选值的总最大值
Posted
技术标签:
【中文标题】所选值的总最大值【英文标题】:The total maximum value of the value chosen 【发布时间】:2019-12-03 18:42:59 【问题描述】:问题:
给定一个值数组 [a0,a1,a2,..,an]
根据以下规则选择值:
一个回合只能取一个值。
如果本次已经选择了数组中的第k个值,那么下一回合只能选择k+1到n-1的值。
在奇数转(第 1 转,第 3 转,...)。选择任意值。
在偶数转弯时(第 2 回合、第 4 回合……)。选择一个与前一个值相同的值。
查找并打印我可以选择的值的总最大值
示例:
使用 a=[2,5,2,6]。
转1,选2。
转2,选择2。
转 3,选择 6。
总最大值为 10使用 a=[6,11,14,0,10,1,11,7,7,11,11,14,14,13,9,0,12,9,11,3]。
总最大值为 115
我的代码:
def firstpair(a):
for i in range(len(a)):
for j in range(i+1,len(a)):
if a[i]==a[j]:
return [i,j]
return []
def chooseValues(a):
s = firstpair(a)
if len(s)==0:
if len(a)==0: return 0
else: return max(a)
if s[0]==0: x=0
else:
x = max(a[:s[0]])
y = a[s[0]]+a[s[1]]+chooseValues(a[s[1]+1:])
z = chooseValues(a[s[0]+1:])
return max(x,y,z)
我可以降低上述解决方案的空间复杂度吗?
【问题讨论】:
【参考方案1】:我认为你可以通过倒退来处理 n
空间和时间复杂度:
def max_value(items):
best = [0 for _ in items] + [0]
last_seen =
for i in reversed(xrange(len(items))):
curr = items[i]
pair = last_seen.get(curr)
if pair is None:
choose_this = curr
else:
choose_this = curr * 2 + best[pair + 1]
best[i] = max(choose_this, best[i + 1])
last_seen[curr] = i
return best[0]
如果您想让它复杂一点,您可以通过组合 last_seen
和 best
以更少的存储空间(与唯一值成正比)来做到这一点:
def max_value(items):
best_rest = None: 0
best_max = 0
for i in reversed(range(len(items))):
curr = items[i]
choose_this = curr * 2 + best_rest.get(curr, -curr)
best_rest[curr] = choose_rest = best_max
best_max = max(choose_this, choose_rest)
return best_max
无论哪种情况:
assert max_value([6, 11, 14, 0, 10, 1, 11, 7, 7, 11, 11, 14, 14, 13, 9, 0, 12, 9, 11, 3]) == 115
assert max_value([2, 5, 2, 6]) == 10
【讨论】:
具有讽刺意味的是,我们拥有的唯一值越多(过去 n/2),我们需要存储的就越少。 后退比前进有什么好处?如果我在您的代码中切换方向,似乎没有什么不同。 @גלעדברקן 它应该有所作为,因为问题并不总是对称的,例如:[2,1,2,1] -> 5
,但 [1,2,1,2] -> 4
。
是的,我不得不在我的脑海中扭动一下,看看它是否是真的 =) 无论如何,它仍然会通过从右到左进行处理来尊重原始问题,以便可以将其与问题进行比较描述和典型的人类尝试,而不是潜在等效的相反顺序。
不过,你还没有回答我的问题。后退比前进有什么好处?【参考方案2】:
这是一种思考方式。让f(i, parity)
表示在具有奇偶性parity
的步骤中选择i
th 元素时达到的最大值。那么:
f(i, even) = A[i] + max(f(j, odd)) // requires O(1) storage
where j < i and A[j] == A[i]
f(i, odd) = A[i] + max(f(j, even)) // requires O(num_unique_Ai) storage
where j < i
def f(A):
max_f_j_even = -float("inf")
max_f_j_odd = A[0]: A[0]
best = -float("inf")
for i in range(1, len(A)):
# Even turn
new_max_f_j_even = None
if A[i] in max_f_j_odd:
new_max_f_j_even = max(max_f_j_even, A[i] + max_f_j_odd[A[i]])
# Odd turn
else:
# A[i] is a first turn
max_f_j_odd[A[i]] = A[i]
# A[i] is a later odd turn
max_f_j_odd[A[i]] = max(max_f_j_odd[A[i]], A[i] + max_f_j_even)
if new_max_f_j_even != None:
max_f_j_even = new_max_f_j_even
best = max(best, max_f_j_even, max_f_j_odd[A[i]])
return best
A = [2,5,2,6]
print(f(A)) # 10
A = [6,11,14,0,10,1,11,7,7,11,11,14,14,13,9,0,12,9,11,3]
print(f(A)) # 115
【讨论】:
以上是关于所选值的总最大值的主要内容,如果未能解决你的问题,请参考以下文章