我正在练习一些动态编程问题,并且遇到了这个问题
给出一个n(1<=n<=1000)
整数和一个正整数k(k<=1000)
的数组。找到最长的子序列,其总和可被k
整除。
例如a = [1,6,11,5,10,15,20,2,4,9]
和k=5
。
结果应为:[9,4,20,15,10,5,11,6]
,因为9+4+20+15+10+5+11+6 = 80
可以被5整除。
什么是解决此问题的合适方法?
答案 0 :(得分:2)
暴力法:
我们可以生成所有可能的子序列,然后在它们之间求和并被K
整除的最大子序列。
但是,这种方法的时间复杂度为O(n*n)
。
有效方法:
我们可以在此处使用 动态编程 。请注意,这种方法仅适用于K
的较小值。
dp[i][curr_mod] = max(dp[i + 1][curr_mod], dp[i + 1][(curr_mod + arr[i]) % m] + 1)
在这里,dp[i][curr_mod]
存储子数组arr[i…N-1]
的最长子序列,以使该子序列和curr_mod
的和可被K
整除。
在每个步骤中,可以选择index i
来更新curr_mod
,也可以将其忽略。
另外,请注意,仅需要存储 SUM%m 而不是全部和,因为此信息足以完成DP的状态。
答案 1 :(得分:1)
从最长的子序列开始,即数组本身。计算其总和模k。如果它为零,我们就完成了。否则,找到一个数字,以使其模k相同。如果存在,请将其删除,我们完成了。否则继续前进。