Given a set of distinct positive integers, find the largest subset such that every pair (Si, Sj) of elements in this subset satisfies: Si % Sj = 0 or Sj % Si = 0.
If there are multiple solutions, return any subset is fine.
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]
求满足条件的最长序列,有两种解法:
解法一:暴力求解,采用回溯算法,时间复杂度高,尽管中间采用了剪枝,仍会TLE。程序如下:
class Solution {
List<Integer> list = new ArrayList<>();
public List<Integer> largestDivisibleSubset(int[] nums) {
Arrays.sort(nums);
backTracing(nums, 0, new ArrayList<>());
return list;
}
public void backTracing(int[] nums, int begin, List<Integer> l){
if (begin >= nums.length){
if (list.size() < l.size()){
list = new ArrayList<>(l);
}
return;
}
if (list.size() >= nums.length - begin + l.size()){
return;
}
for (int i = begin; i < nums.length; ++ i){
boolean tag = false;
if (l.size() == 0){
l.add(nums[i]);
tag = true;
}
else if ((nums[i]%l.get(l.size() - 1)) == 0){
l.add(nums[i]);
tag = true;
}
backTracing(nums, i+1, l);
if (tag){
l.remove(l.size() - 1);
}
}
}
}
解法二:根据LIS(最大递增子序列)算法求解,其实最大递增、最大满足mod为零递增,只是不同的条件而已,算法的框架可以复用,由于需要返回最长的子序列,因此用了一个last数组保存上一个序列的小标,程序如下所示:
class Solution {
List<Integer> list = new ArrayList<>();
public List<Integer> largestDivisibleSubset(int[] nums) {
Arrays.sort(nums);
int[] cur = new int[nums.length];
int[] last = new int[nums.length];
Arrays.fill(last, -1);
int index = -1, maxLen = 0;
for (int i = 1; i < nums.length; ++ i){
for (int j = 0; j < i; ++ j){
if ((nums[i]%nums[j]) == 0){
if (cur[i] <= cur[j]){
cur[i] = cur[j] + 1;
last[i] = j;
}
if (cur[i] > maxLen){
maxLen = cur[i];
index = i;
}
}
}
}
while (index != -1){
list.add(0, nums[index]);
index = last[index];
}
if (list.size() == 0&&nums.length != 0){
list.add(nums[0]);
return list;
}
return list;
}
}