我正在练习动态编程,而且我正在编写最长的后续子序列问题。
我有DP解决方案:
export function addTab(name, icon) {
return (dispatch) => {
dispatch({ type: 'TABS_POST_START' });
return axios({
method: 'POST',
url: '/rest-api/ui/tabs/',
headers: {
'X-CSRFToken': CSRF_TOKEN,
'Content-Type': 'application/json'
},
data: {
name,
icon
},
})
.then((response) => {
dispatch({ type: 'TABS_POST_SUCCESS' });
dispatch({ type: 'TABS_ADD', tab: response.data });
})
.catch((err) => {
dispatch({ type: 'TABS_POST_FAILURE', payload: err });
});
};
}
export function fetchTabs() {
return (dispatch) => {
dispatch({ type: 'TABS_FETCH_START' });
return axios.get('/rest-api/ui/tabs/')
.then((response) => {
dispatch({ type: 'TABS_FETCH_SUCCESS' })
dispatch({ type: 'TABS_SET', tabs: response.data });
})
.catch((err) => {
dispatch({ type: 'TABS_FETCH_FAILURE', payload: err });
});
};
}
一个非记忆版
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)]
但是,这两个功能有不同的行为。例如,测试用例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
对于memoized版本失败。
longest_subsequence([10,9,2,5,3,7,101,18])
然而,非记忆版本完全正确(虽然慢得多)。
>>> longest_subsequence([10,9,2,5,3,7,101,18])
[10, 101]
我做错了什么?
编辑: Tempux的答案在以下方面失败:
>>> longest_subsequence([10,9,2,5,3,7,101,18])
[2, 5, 7, 101]
非记忆版本的解决方案是:
>>> longest_subsequence([3,5,6,2,5,4,19,5,6,7,12])
[3, 5, 6, 7, 12]
答案 0 :(得分:4)
您的州取决于lst
和之前选择的项目。但你只考虑lst
。这就是为什么你得到不正确的结果。要解决此问题,您只需将上一项添加到动态状态即可。
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])
请注意,使用tuple(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])
要获得更有效的方法,您可以查看this问题。
答案 1 :(得分:0)
所以我刚刚发现Tempux的答案并不适用于所有情况。
我回过头来将整个状态封装到memoization字典中,从而添加了tuple(lis)
作为密钥的一部分。此外,lst
索引技巧可能不容易实现,因为我通过递归变异lst
,因此我使用tuple()
作为我的键。
我所做的背后的原因是多个lis
可能具有相同的[-1]
值。因此,使用这个新状态,代码是:
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))]
这适用于我目前测试过的所有情况。