【LeetCode刷题】5343. 多次求和构造目标数组:妙解

给你一个整数数组 target 。一开始,你有一个数组 A ,它的所有元素均为 1 ,你可以执行以下操作:

 x 为你数组里所有元素的和,选择满足 0 <= i < target.size 的任意下标 i ,并让 A 数组里下标为 i 处的值为 x 。你可以重复该过程任意次。如果能从 A 开始构造出目标数组 target ,请你返回 True ,否则返回 False

   

示例 1

输入:target = [9,3,5]

输出:true

解释:从 [1, 1, 1] 开始

[1, 1, 1], 和为 3 ,选择下标 1

[1, 3, 1], 和为 5, 选择下标 2

[1, 3, 5], 和为 9, 选择下标 0

[9, 3, 5] 完成

示例 2

输入:target = [1,1,1,2]

输出:false

解释:不可能从 [1,1,1,1] 出发构造目标数组。

示例 3

输入:target = [8,5]

输出:true

   

提示:

N == target.length

1 <= target.length <= 5 * 10^4

1 <= target[i] <= 10^9

解题思路

查找规律题

既然是将sum加到某个位置,那么该位置一定是数组中的最大值。这样,每一轮寻找数组的最大值max和总和sum 那么数组最大值的位置改变为max-sum-max)就是上一轮操作的数组,倒着往前操作,直到sum==n&&max==1 返回true 或者 max-(sum-max) 小于等于0 返回false;

   

深度优先搜索,先求了和避免冗余计算,但要注意int范围越界的问题,wa了一次。

可以证明和不会超过最大整数的两倍,求和的时候做一下判断即可。

class Solution {

public:

bool flag = false;

 

void dfs(vector<int>& target, long sum) {

if (flag) return;

if (sum == target.size()) {flag = true;return;}

for (int i = 0; i < target.size(); i++) {

if ((long)2*target[i] <= sum) continue;

int origin = target[i];

target[i] = 2*target[i] - sum; //最大的那个那个就是其他的和+原来的他自己,sum中包含了一个他自己故乘二

dfs(target, sum-origin+target[i]);

target[i] = origin;

}

}

 

bool isPossible(vector<int>& target) {

long sum = 0;

for (auto num: target) {

if (sum >= (long)2*INT_MAX-num) {return false;}

sum += num;

}

dfs(target, sum);

 

return flag;

}

};

   

作者:wfnuser

链接:https://leetcode-cn.com/problems/construct-target-array-with-multiple-sums/solution/c-dfs-shuang-bai-by-wfnuser/

来源:力扣(LeetCode

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

posted @ 2020-02-16 17:24  拓海藤原  阅读(299)  评论(0编辑  收藏  举报