这是leetcode上的关于动态规划的一道题,先来看下原题:
368. Largest Divisible Subset QuestionEditorial Solution My Submissions
Total Accepted: 3593
Total Submissions: 12097
Difficulty: Medium
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]
要求子数组里任何两个元素均要满足互余。这道题看起来好像有点复杂,但是解题的思路很直接。最方便的做法是先对数组进行排序。然后比较nums[i]与nums[j]是否互余:
if nums[i] % nums[j] = 0 then leng[i] = leng[j] + 1
leng[i]表示的是到i这个位置时,满足条件的子数组长度。
下面给出两种方法,思路是一样的。不同的是借助的数据结构不同:第一种方法利用List
public List<Integer> largestDivisibleSubset1(int[] a) {
List<List<Integer>> list = new ArrayList<List<Integer>>();
if(a.length < 1) return new ArrayList<Integer>();
int max = 0;
int p = 0;
for(int k = 0; k < a.length; k++){
list.add(k, new ArrayList<Integer>());
}
if(a.length >= 1){
Arrays.sort(a);
int[] leng = new int[a.length];
int j = 0;
for(int i = 0; i < a.length; i++){
for(j = i - 1; j >= 0; j--){
if(a[i] % a[j] == 0 && a[i] > a[j]){
if(leng[i] < leng[j] + 1){
leng[i] = leng[j] + 1;
list.set(i,new ArrayList<Integer>(list.get(j)));
list.get(i).add(a[i]);
if(max < leng[i]) {
max = leng[i];
p = i;
}
}
}
}
if(j < 0 && leng[i] == 0) {
list.get(i).add(a[i]);
leng[i] = 1;
}
}
}
return list.get(p);
}
第二种方法(借助path数组):
public List<Integer> largestDivisibleSubset(int[] a){
List<Integer> list = new ArrayList<Integer>();
if(a.length < 1) return list;
Arrays.sort(a);
int[] path = new int[a.length];
int[] fun = new int[a.length];
int i = 0, j = 0;
int max = 0, p = 0;
for(i = 0; i < a.length; i++){
for(j = i - 1; j >= 0; j--){
if(a[i] % a[j] == 0){
if(fun[i] < fun[j] + 1){
fun[i] = fun[j] + 1;
path[i] = j;
}
if(max < fun[i]){
max = fun[i];
p = i;
}
}
}
if(j < 0 && fun[i] == 0){
fun[i] = 1;
if(max < 1) {
max = 1;
}
}
}
while(max>0){
list.add(0, a[p]);
p = path[p];
max--;
}
return list;
}