题目描述
给出一个数字集合,包含各不相同的若干正整数。找到最大的子集,使得这个子集里的任意两个元素(Si, Sj)满足Si % Sj = 0 或者 Sj% Si = 0。
Example 1:
nums: [1,2,3]Result: [1,2] (of course, [1,3] will also be ok)
Example 2:
nums: [1,2,4,8]Result: [1,2,4,8]
算法分析
题目要求我们在一个集合中寻找一个满足条件的子集。对于这类对顺序没有要求的序列问题,我们总是可以选择先进行排序。
假设我们从小到大排序了nums数组,那么我们在小到大选取元素(加入子集)的过程中一定满足一个性质:所有选取的元素都是新加入的元素的因子,进一步发现,子集中第一个元素(最小的)是第二个元素的因子,第二个是第三个的因子,依次类推...,最后组成了一个序列,而我们要做的就是找出这样最长的序列。
可以明显的注意到,这个问题是分阶段的,我们可以通过保存局部的最优解,来加速整个穷举过程,也就是用动态规划算法。用f[i]表示前i个数(第i个一定在子集中)可以组成的最大的满足条件的子集,转移方程如下:
f[i] = max{f[j]}, if i mod j = 0
f[i]一开始均初始化为1。
最后的答案保存在f[i]的最大值中。
此外,本题还需要输出子集中所有的元素,因此我们需要用一个pre数组纪录每个位置是从之前哪个位置转移而来。
参考代码
面试官角度分析
本题是个中等难度的题目,要一下子想到动态规划的算法不易,需要对动态规划有深入理解。给出动态规划算法可以达到hire的程度。
LintCode相关练习题
http://www.lintcode.com/zh-cn/problem/climbing-stairs/
专业的北美IT求职经验分享,技术交流社区,帮助你找到好的IT工作。
由硅谷顶尖的IT企业工程师授课,提供专业的算法培训/面试咨询。
官网:www.jiuzhang.com
微信公众号:九章算法。
知乎ID:九章算法。