LeetCode 368

题目描述:

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<j,如果 nums[k]%nums[j]==0 则一定有 nums[k]%nums[i] == 0

如此,该题目只需要维护一个一维数组即可得到结果。不过只是动归的话,仅能得到subset的大小,如果要得到subset的具体值,参照Dijkstra,再维护一个数组以记录last node,最后只需要回溯一下就OK。

AC代码:

 1 public int[] sort(int [] nums){
 2         int k, min;
 3         for (int i = 0; i< nums.length; i++){
 4             min = Integer.MAX_VALUE;
 5             k = 0;
 6             for (int j = i; j< nums.length; j++){
 7                 if ( min > nums[j]){
 8                     min = nums[j];
 9                     k = j;
10                 }
11             }
12             nums[k] = nums[i];
13             nums[i] = min;
14         }
15         
16         return nums;
17     }
18     
19     public List<Integer> largestDivisibleSubset(int[] nums){
20         if (nums.length <= 0) return new ArrayList<Integer>();
21         nums = sort(nums);
22         int size = nums.length;
23         int [] times = new int[size];
24         int [] index = new int[size];
25         for (int i = 0; i< size; i++){
26             times[i] = 1;
27             index[i] = -1;
28         }
29         for (int i = 0; i< size; i++){
30             for (int j = 0; j< i; j++){
31                 if (nums[i]%nums[j] == 0 && times[j] + 1 > times[i]){
32                     times[i] = times[j] + 1;
33                     index[i] = j;
34                 }
35             }
36         }
37         int k = 0, max = 0;
38         for (int i = 0; i < size; i++){
39             if (max <= times[i]){
40                 k = i; max = times[i];
41             }
42         }
43         List<Integer> res = new ArrayList<Integer>();
44         while(k >= 0){
45             res.add(nums[k]);
46             k = index[k];
47         }
48         return res;
49     }

 

经验&教训:

第一次我不是这样想的,第一次我是想,对于集合{a, b, c, d, e},先判断集合是否满足两两整除,如果不是,则分别考虑5个只有4个元素的子集,分别寻找子集中的最大子集。如此,复杂度为2^n。

主要是没有注意到,如果把集合排序,会有什么样的特性。有序数据真是创造奇迹的存在啊

posted @ 2016-07-20 22:20  打不死的流云  阅读(252)  评论(0编辑  收藏  举报