LeetCode 368. Largest Divisible Subset
LeetCode上的新题(https://leetcode.com/problems/largest-divisible-subset/),看了一下,我怎么觉得这个就是前几个月有一场CSAcademy的原题(https://csacademy.com/contest/archive/#task/divisor_clique/)呢。
CSAcademy这道原题我当时应该没写过题解,因为没什么复杂的地方,数据量也不大。
还是分析一下好了,其实就是要集合中任意两个数字有倍数的关系。所以如果把这个集合按照从小到大写出来的话,一定是前一个能够整除后一个的。
CSAcademy那原题因为规模才2000,直接O(n^2)地去dp一下就好了。
但是LeetCode这题我一开始以为应该是数据量比较大的,可能是卡O(n^2)的,但问题是也不知道这些整数的大小范围。所以一开始试了写O(n*sqrt(m))的复杂度,m为整数的上界。可以通过TL。
后来我又试了一下,发现直接O(n^2)就可以过了。那看来数据规模和CSAcademy那道原题应该没啥区别了。唯一不同之处只是在于需要给出一个list,这个就转移的时候记录一下就好了。
1 public class Solution { 2 public List<Integer> largestDivisibleSubset(int[] nums) { 3 if (nums == null || nums.length == 0) { 4 return new ArrayList<>(); 5 } 6 Arrays.sort(nums); 7 int n = nums.length; 8 int[] dp = new int[n]; 9 int[] last = new int[n]; 10 int max = 0, idx = 0; 11 for (int i = 0; i < n; i++) { 12 dp[i] = 1; 13 last[i] = -1; 14 for (int j = 0; j < i; j++) { 15 if (nums[i] % nums[j] == 0 && dp[j] + 1 > dp[i]) { 16 dp[i] = dp[j] + 1; 17 last[i] = j; 18 } 19 } 20 if (max < dp[i]) { 21 max = dp[i]; 22 idx = i; 23 } 24 } 25 List<Integer> list = new ArrayList<>(); 26 do { 27 list.add(nums[idx]); 28 idx = last[idx]; 29 } while (idx != -1); 30 return list; 31 } 32 }