最长可除序列
Posted 贾斯彼迭
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最长可除序列相关的知识,希望对你有一定的参考价值。
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; }
以上是关于最长可除序列的主要内容,如果未能解决你的问题,请参考以下文章