本教程将讨论一个问题,其中给定了一组不同的正整数。我们需要找到最大的子集,使得每对较大的元素除以较小的元素,例如 -
Input: nums[ ] = { 1, 4, 2, 6, 7} Output: 1 2 4 Explanation: All Divisible subsets are: (1, 2, 4), (1, 2, 6), (1, 7), etc We have 2 subsets of length 3 in which all the pairs satisfy the condition. Input: nums[ ] = { 1, 2, 3, 6 } Output: 6 2 1
我们将在本教程中解释两种不同的方法。
用一个简单的方法,我们可以应用递归来解决这个问题。我们将获取每个元素并检查它是否应将其包含在子集中。假设我们从第一个元素开始。我们将有两个选项,要么包含在子集中,要么不包含在第一个元素中。让我们包含第一个元素。那么对于要包含在子集中的第二个元素,它应该可以被子串中的元素整除或相除,即第一个元素。这就是我们将如何遍历整个数组。因此将有 2^n 条可能的路径来创建 O(2^n) 的时间复杂度。让我们来看看解决这个问题的可行方法。
在这个问题中使用动态规划可以应用一种有效的方法。
对数组进行排序以获得可被正确元素整除的左侧元素。我们必须检查一次可分性。
我们将采用最长递增子序列,即我们的 dp[ ] 数组,来存储直到第 i 个索引的最大可整除子集。我们将用 1 初始化每个索引,因为每个元素都会自我划分。
现在我们将从第二个索引开始迭代并检查每个元素以获取以当前索引结尾的最大可分子集。这样,我们将找到每个索引的最大子集。
现在遍历数组,并为每个元素找到一个可整除计数最大的除数。并将当前索引的可整除计数值更改为该元素的可整除计数+1。
上述方法的 C++ 代码
#include<bits/stdc++.h> using namespace std; int main(){ int nums[] = {1, 2, 3, 6}; int n = sizeof(nums)/sizeof(int); // 对数组进行排序以排除一个除法条件。 sort(nums, nums+n); vector <int> prev_res(n, -1); // 存储所有元素的除数的向量 vector <int> dp(n, 1); int max = 1; for (int i=1; i<n; i++){ // 检查第 j 个索引处是否存在第 i 个元素的除数。 for (int j=0; j<i; j++){ if (nums[i]%nums[j] == 0){ // 检查是否添加会增加子序列中的元素数量。 if (dp[i] < dp[j] + 1){ dp[i] = dp[j]+1; prev_res[i] = j; } } } // 查找具有最大子集数的索引。 if(max<dp[i]) max = dp[i]; } cout << "数组中最大的可分子集: "; // 打印最大子集 int k = max; while (k >= 0){ cout << nums[k] << " "; k = prev_res[k]; } return 0; }输出结果
数组中最大的可分子集: 6 2 1
在本教程中,我们讨论了一个问题:我们需要在给定数组中找到最大的可整除子集,其中每对中的整数都是可整除的。我们讨论了一种递归方法,它会产生指数时间复杂度,因此我们讨论了动态规划解决方案。我们还讨论了针对这个问题的 C++ 程序,我们可以使用 C、Java、Python 等编程语言来解决这个问题。我们希望本教程对您有所帮助。