所选值的总最大值

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_seenbest 以更少的存储空间(与唯一值成正比)来做到这一点:

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 的步骤中选择ith 元素时达到的最大值。那么:

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

【讨论】:

以上是关于所选值的总最大值的主要内容,如果未能解决你的问题,请参考以下文章

隐藏所有id不是所选值的tr

从下拉列表中更新所选值的 mysql 记录

使用 Angular 复制带有 UI 和所选值的下拉列表

Angular 材质:在下拉列表中获取所选值的 id

Ember JS:选择具有所选值的列表

在c#MVC4中获取列表框中所选值的总和