小易的幸运数字是7,现有一个整数数组 nums,请你找出并返回能被七整除的子集合的最大和,如果找不到则返回-1。
一个正整数数组列表nums,用空格区分,1<=length(nums)<=100000,sum(nums) <= 1000000000
一个整数,最大和
7 3 1 4
14
7+3+4
6 5
-1
找不到 一个子数组,和能被7整除
10 20 2 29
49
20+29
这道题很难, 一开始会想到遍历得到所有的子集合的和, 但是却不知道如何遍历得到。因为这里的子集合长度可以为1 ~ nums.length,一般的遍历无法满足!
举例: 1 2 3 4
一般的遍历是 1, 1 2, 1 2 3, 1 2 3 4, 2, 2 3, 2 3 4, 3,3 4,4实现这个遍历已经是O(n^2)的复杂度了! 可是这还没结束, 还需要 1 3, 1 3 4, 1 4, 2 4, 这种循环遍历极其难写出来!!
🌟那我们这里想到了一个巧妙地方法, 逆向思维, 由于全部的数之和sum肯定是由所有的数组成, 那我们可以试着慢慢地扒元素下来直到把所有元素扒完,
const readline=require('readline'); const rl=readline.createInterface({ input:process.stdin, output:process.stdout }); /* 小易的幸运数字是7,现有一个整数数组 nums, 请你找出并返回能被七整除的子集合的最大和,如果找不到则返回-1 输入: 一个正整数数组列表nums,用空格区分,1<=length(nums)<=100000,sum(nums) <= 1000000000 */ rl.on('line',function (line) { /*1.处理数据*/ let arr=line.trim().split(' ').map(Number); /*2.dp*/ //由于是全是正整数,所以 sum >= arr.length let sum=arr.reduce((a,b)=>a+b); //dp[i]记录i是否能够得到 1为可得到,0则相反 let dp=new Array(sum+1).fill(0); dp[0]=1; dp[sum]=1; /*这个方法很巧妙, 最初是a+b+c+d,每次从所有的满足条件的子集合减去一个数 * 这样就很方便的得到了所有的排列*/ for (let i=0;i<arr.length;i++){ for (let j=0;j<=sum;j++){ if (dp[j]===1&&j>=arr[i]){ dp[j-arr[i]]=1; } } } let maxSum=-1; for (let i=dp.length-1;i>=7;i--){ if (dp[i]===1&& i%7===0){ maxSum=i; break; } } console.log(maxSum); })