【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)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。