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
.
Example
Given nums = [1,2,3]
, return [1,2]
or [1,3]
Given nums = [1,2,4,8]
, return [1,2,4,8]
类似最长增长子序列。需要返回子序列,刚开始想到把每种可能都存在单独的list里,并不是很优化的做法。只需找到最长的那个可除序列,再遍历一遍,把数都存在list里面即可;
本题亮点是用到了回溯。所以,除了需要dp数组外,还需要额外的pre数组记录每个数的前继点。
首先,对数组排序,正序逆序都无所谓吧,不排序太复杂了;这里采用正序。
dp[i]表示,arr[i]能整除前面1~i-1个数的个数。递推过程是,if nums[i] % nums[j] == 0 , dp[i] = max{dp[i], dp[j] + 1}, j < i
初始条件,dp[i] = 1; pre[i] = -1; 表示每个数在开算之前,长度最少为1, 前继至少是-1;
同时,需要全局变量记录出现最大序列长度的位置。
public static List<Integer> largestDivisibleSubset(int[] nums) {
// Write your code here
List<Integer> list = new ArrayList<>();
if(nums == null || nums.length == 0)
return list;
Arrays.sort(nums);
int len = nums.length;
int[] dp = new int[len];
int[] pre = new int[len];
int max = 0, index = -1;
for(int i = 0; i < len; i++){
dp[i] = 1;
pre[i] = -1;
for(int j = i-1; j >= 0; j--){
if(nums[i] % nums[j] == 0 && dp[j] + 1 > dp[i]){
dp[i] = dp[j] + 1;
pre[i] = j;
}
}
if(dp[i] > max){
max = dp[i]; // 更新最大值位置
index = i;
}
}
while(index != -1){
list.add(nums[index]); // 回溯找到每个数
index = pre[index];
}
return list;
}