一、Problem
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 that 0 <= i < target.size and set the value of A at index i to x.
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.
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
二、Solution
方法一:暴力排序(超时)
- 逆向思维,从 target 变为全 1 数组怎么做?
- 我们知道将 [1, 3, 1] 变为 [1, 1, 1] 需要将 a 排序,然后由 a[2] -= a[0] + a[1] 得出公式: -=
class Solution {
long sum(int[] a, int r) {
long sum = 0;
for (int i = 0; i < r; i++) sum += a[i];
return sum;
}
public boolean isPossible(int[] tar) {
int n = tar.length-1;
Arrays.sort(tar);
while (tar[n] > 1) {
if (tar[0] < 0) return false;
tar[n] -= sum(tar, n);
Arrays.sort(tar);
}
return tar[0] == 1;
}
}
复杂度分析
- 时间复杂度:,
- 空间复杂度:,
方法二:暴力优化(超时)
由上可得,上一轮的被赋值的元素 = 这一轮的最大值 ,故,我们只需记录每一轮的最大值 ,以及其下标 ,即可省去冗余的排序。同时我们需要明确几个结束条件即可判断是否能由 target 变为全 1 数组:
- 因为数组至少存在两个元素,所以当某一轮改变后,发现 sum < 2,return false
- 因为能被构造出来的最小元素一定不小于 1,所以当某一轮的元素
2 × maxn - sum
比 1 小了,return false - 如果最后
maxn = 1 && sum = n
,说明构造成功…
class Solution {
public boolean isPossible(int[] tar) {
int n = tar.length;
while (true) {
int maxi = 0;
long maxn = 0, sum = 0;
for (int i = 0; i < n; i++) {
sum += tar[i];
if (tar[i] > maxn) {
maxi = i;
maxn = tar[i];
}
}
if (sum < 2) break;
if (maxn == 1 && sum == n) return true;
if (2*maxn - sum < 1) return false;
tar[maxi] = (int) (2*maxn - sum);
}
return false;
}
}
复杂度分析
- 时间复杂度:,
- 空间复杂度:,