1354. Construct Target Array With Multiple Sums
Given an array of integers target
. From a starting array, A
consisting of all 1's, you may perform the following procedure :
- let
x
be the sum of all elements currently in your array. - choose index
i
, such that0 <= i < target.size
and set the value ofA
at indexi
tox
. - You may repeat this procedure as many times as needed.
Return True if it is possible to construct the target
array from A
otherwise return False.
Example 1:
Input: target = [9,3,5]
Output: true
Explanation: Start with [1, 1, 1]
[1, 1, 1], sum = 3 choose index 1
[1, 3, 1], sum = 5 choose index 2
[1, 3, 5], sum = 9 choose index 0
[9, 3, 5] Done
Example 2:
Input: target = [1,1,1,2]
Output: false
Explanation: Impossible to create target array from [1,1,1,1].
Example 3:
Input: target = [8,5]
Output: true
Constraints:
N == target.length
1 <= target.length <= 5 * 10^4
1 <= target[i] <= 10^9
题目链接:
https://leetcode-cn.com/problems/construct-target-array-with-multiple-sums/
思路
试着做几个样例,可找到几个规律:
1)计算过程可逆,可从结果倒推回全1的数组;
2)最大值一定要大于其他值之和;
3)由2)可以推出,不能同时存在两个相同的最大值;
4)由3)可以推出,给出的数组中,所有非1的值都必须唯一,因为他们在逆计算时都有机会成为最大值。
因此,由1)可以定下程序的总体思路是逆推,直到数组变回全1,或者中途违反了其他规律而失败。
但这里有个坑:计算超时。样例: [1, 1000000000]。
因此这个过程肯定还有可压缩的地方,是我们没有找到的规律。参考这个未通过样例,可以看出另一个规律:
5)当某个值连续几次都最大时,其他值没有改变,只有它本身不断减去其他值,连续减的结果 = 取余。
6)结合2)和5)可推出,如果最大值取余为0了,而第二大的数却不是1,说明最大值没有满足2),可以提前判定失败。
ok差不多了,上代码。
class Solution {
public:
bool isPossible(vector<int>& target) {
if(target.size()==0) return true;
if(target.size()==1 ){
if(target[0]==1) return true;
else return false;
}
priority_queue<int> record;
long sum = 0;
for(int i=0; i<target.size(); ++i){
record.push(target[i]);
sum += target[i];
}
while(sum>target.size()){
int iter = record.top();
record.pop();
if(iter == 1) return true;
if(iter > sum - iter){
if(record.top() == 1) return true;
int tmp = sum - iter;
int sub = iter / tmp;
int num = iter % tmp;
if(num == 0) return false;
record.push(num);
sum -= tmp * sub;
}else return false;
}
return true;
}
};