简体   繁体   English

如何正确记住这个 LIS python2.7 算法?

[英]How do I memoize this LIS python2.7 algorithm properly?

I'm practicing Dynamic Programming and I am writing the Longest Increasing Subsequence problem.我正在练习动态规划,并且正在编写最长递增子序列问题。

I have the DP solution:我有DP解决方案:

def longest_subsequence(lst, lis=[], mem={}):
  if not lst:
    return lis
  if tuple(lst) not in mem.keys():
    if not lis or lst[0] > lis[-1]:
      mem[tuple(lst)] = max([longest_subsequence(lst[1:], lis+[lst[0]], mem), longest_subsequence(lst[1:], lis, mem)], key=len)
    else:
     mem[tuple(lst)] = longest_subsequence(lst[1:], lis, mem)
  return mem[tuple(lst)]

And a non-memoized version和一个非记忆版本

def longest_subsequence(lst, lis=[]):
  if not lst:
    return lis
  if not lis or lst[0] > lis[-1]:
    result = max([longest_subsequence(lst[1:], lis+[lst[0]]), longest_subsequence(lst[1:], lis)], key=len)
  else:
    result = longest_subsequence(lst[1:], lis)
  return result

However, the two functions have different behaviours.但是,这两个函数具有不同的行为。 For example, the test case longest_subsequence([10,9,2,5,3,7,101,18]) fails for the memoized version.例如,测试用例longest_subsequence([10,9,2,5,3,7,101,18])对于记忆版本失败。

>>> longest_subsequence([10,9,2,5,3,7,101,18])
[10, 101]

The non-memoized version is fully correct however (although much slower).然而,非记忆版本是完全正确的(虽然慢得多)。

>>> longest_subsequence([10,9,2,5,3,7,101,18])
[2, 5, 7, 101]

what I am doing wrong?我做错了什么?

Your state depends on both lst and previous item you have picked.你的状态取决于两个lst和您已选择了一个项目。 But you are only considering the lst .但你只考虑lst That is why you are getting incorrect results.这就是为什么你得到不正确的结果。 To fix it you just have to add previous item to your dynamic state.要修复它,您只需将上一个项目添加到您的动态状态。

def longest_subsequence(lst, prev=None, mem={}):
  if not lst:
    return []
  if (tuple(lst),prev) not in mem:
    if not prev or lst[0] > prev:
      mem[(tuple(lst),prev)] = max([[lst[0]]+longest_subsequence(lst[1:], lst[0]), longest_subsequence(lst[1:], prev)], key=len)
    else:
     mem[(tuple(lst),prev)] = longest_subsequence(lst[1:], prev)

  return mem[(tuple(lst),prev)]

print longest_subsequence([3,5,6,2,5,4,19,5,6,7,12])

Note that using the tuple(list) as your dynamic state is not a very good idea.请注意,使用tuple(list)作为您的动态状态并不是一个好主意。 You can simply use the index of the item in the list that you are checking instead of the whole list:您可以简单地使用您正在检查的list中项目的索引而不是整个列表:

def longest_subsequence(lst, index=0, prev=None, mem={}):
  if index>=len(lst):
    return []
  if (index,prev) not in mem:
    if not prev or lst[index] > prev:
      mem[(index,prev)] = max([[lst[index]]+longest_subsequence(lst, index+1, lst[index]), longest_subsequence(lst, index+1, prev)], key=len)
    else:
      mem[(index,prev)] = longest_subsequence(lst,index+1, prev)

  return mem[(index,prev)]

print longest_subsequence([3,5,6,2,5,4,19,5,6,7,12])

For more efficient approaches you can check this question.对于更有效的方法,您可以检查问题。

So I had just discovered that Tempux's answer did not work for all cases.所以我刚刚发现 Tempux 的答案并不适用于所有情况。

I went back and through about encapsulating the entire state into the memoization dictionary and thus added tuple(lis) as part of the key.我反复讨论将整个状态封装到记忆字典中,因此添加了tuple(lis)作为键的一部分。 Also, the lst index trick may not be as easy to implement since I am mutating lst through the recursion, hence why I am using tuple() as my keys.此外, lst索引技巧可能并不容易实现,因为我通过递归改变lst ,因此我使用tuple()作为我的键。

The reasoning behind what I did is that multiple lis may have the same [-1] value.我所做的背后的原因是多个lis可能具有相同的[-1]值。 So, with this new state, the code is:所以,有了这个新状态,代码是:

def longest_subsequence(lst, lis=[],mem={}):
  if not lst:
    return lis
  if (tuple(lst),tuple(lis)) not in mem:
    if not lis or lst[0] > lis[-1]:
      mem[(tuple(lst),tuple(lis))] = max([longest_subsequence(lst[1:], lis+[lst[0]]), longest_subsequence(lst[1:], lis)], key=len)
    else:
     mem[(tuple(lst),tuple(lis))] = longest_subsequence(lst[1:], lis)
  return mem[(tuple(lst),tuple(lis))]

This works for all cases I have tested so far.这适用于我迄今为止测试过的所有情况。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM