首页 > 其他分享 >[LeetCode] 1354. Construct Target Array With Multiple Sums 多次求和构造目标数组

[LeetCode] 1354. Construct Target Array With Multiple Sums 多次求和构造目标数组

时间:2023-10-15 09:04:54浏览次数:46  
标签:Multiple Target sum Sums 数组 target array true 数字


You are given an array target of n integers. From a starting array arr consisting of n 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 < n and set the value of arr 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 arr, otherwise, return false.

Example 1:

Input: target = [9,3,5]
Output: true
Explanation: Start with arr = [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 <= n <= 5 * 104
  • 1 <= target[i] <= 109

这道题说是给了一个目标数组 target,让我们从一个长度相同,但是全是1的数组开始变动,变化的规则是可以将任意位置上的数字变成当前数组的数字之和,并说了可以进行任意次数的变化,问最终是否能变化成给定的数组。参见题目中给定的例子不难理解题意,比如例子1中,就通过了三次变换,可以得到目标数组。而例子2,是没法得到的,因为初始数组的和为4,而目标数组中有个2,是小于4的。再比如例子3,题目中没有给变化过程,我们这里自己推导一下吧:

[1, 1] -> [1, 2] -> [3, 2] -> [3, 5] -> [8, 5]

博主最先看到这题的思路就是暴力搜索,从初始数组开始去尝试每一种可能,这种方法虽然可行,但是运算效率十分的低下,当数组的长度很大的时候,会无法通过 OJ,必须要想出更加优化的解法。由于这道题只是问能否组成目标数组,并不要求组成目标数组的不同方法,所以比较好的思路是倒着推,即从目标数组开始,往回推,看是否能得到初始数组。这种方法的优势在于,我们可以优先处理最大的数字,将其尽可能的最快减小到1。就拿题目中的例子1来举例吧,最大的数字是9,这个9怎么来的呢?在上一轮它是所有数字之和,这样话就可以通过减去其它所有数字得到替换之前的数字,即 9 - (5 + 3) = 1,说明是由 [1, 3, 5] 变化来的。接下来处理数字5,同样的方法求替换之前的数字 5 - (3 + 1) = 1,说明是由 [1, 3, 1] 变化来的。接下来处理数字3,同样的方法求替换之前的数字 3 - (1 + 1) = 1,说明是由 [1, 1, 1] 变化来的,这样就反推得到了初始数组。

这个是可以反推回去的情况,接下来想一下不能反推回去的情况,比如例子2中最大的数字是2,而其余数字之和是3,说明这个2并不是由数组之和变化来的,所以不能反推回去。这就是能反推的一个限定条件,即数组中最大的数字要大于其余数字之和,等于都不行,等于的话说明替换前的数字是0,是不对的,同理,最大数字是其余数字之和的整数倍也是不行的,因为最终还是会减到0。另一个限制条件就是其余数字之和也不能是0,因为初始数组每个数字都是1。说完了限制条件,再来说说到达什么条件就知道可以反推到初始数组,首先就是当数组中的最大数字为1的时候,因为此时在反推回去的过程中,上述的限制条件通过了之后,最大数字仍是1,说明所有数字都是1了,就满足条件了。其实还有个判断条件,即当其余数字之和为1的时候就可以返回 true,这个放到后面来解释。

先来解释一下代码,为了更好的取出最大数,这里用个优先队列,将目标数组所有数字放进去,就可以完成自动排序,同时计算出目标数组之和 sum。然后开始 while 循环,首先取出队首元素t,然后计算出其余数字之和,用数组数组总和 sum 减去t。此时需要判断下是否可以返回 true,即t是否等于1,或者其余数字之和 sum 是否等于1(后面讲解)。不能直接返回 true 的话,就来检查上面解释过的限制条件,即若t小于 sum,或者 sum 等于0,或者t是 sum 的整数倍时,都要返回 false。此时t要对 sum 取余,为啥不是相减,而是取余呢,这其实是一种优化,若数组中最大数字远大于其他数字之和,则减过一次之后还有可能大于其余数字之和,这时为了避免大量的重复计算,则可以直接用取余来跳过重复的步骤。

好,现在再来解释一下前面为啥判断 sum 为1的时候,就可以返回 true。因为这种情况只有一种可能,就是数组中只有两个数字,当前数字是2,而另一个数字是1,这种情况下之所以没法通过下一轮遍历中判断最大数字是1来返回 true,是由于任何数字对1取余都会变成0,于是只能通过判断 sum 的值来返回 true 了,这也是用取余操作比较 tricky 的地方。得到新的 t 之后,要将其加到 sum 中,此时的 sum 就是当前数组所有数字之和了,就可以在下一轮循环中,再减去最大数字,从而又可以得到其它数字之和的那个 sum 了,参见代码如下:


class Solution {
public:
    bool isPossible(vector<int>& target) {
        long sum = 0;
        priority_queue<int> pq;
        for (int num : target) {
            pq.push(num);
            sum += num;
        }
        while (true) {
            int t = pq.top(); pq.pop();
            sum -= t;
            if (t == 1 || sum == 1) return true;
            if (t < sum || sum == 0 || t % sum == 0) return false;
            t %= sum;
            sum += t;
            pq.push(t);
        }
        return true;
    }
};

Github 同步地址:

https://github.com/grandyang/leetcode/issues/1354


类似题目:

Minimum Amount of Time to Fill Cups


参考资料:

https://leetcode.com/problems/construct-target-array-with-multiple-sums/

https://leetcode.com/problems/construct-target-array-with-multiple-sums/solutions/510256/java-c-python-backtrack-oj-is-wrong/

https://leetcode.com/problems/construct-target-array-with-multiple-sums/solutions/2189445/visual-explanation-java-max-heap/


LeetCode All in One 题目讲解汇总(持续更新中...)

标签:Multiple,Target,sum,Sums,数组,target,array,true,数字
From: https://www.cnblogs.com/grandyang/p/17765199.html

相关文章

  • [ARC116C] Multiple Sequences题解
    思路我们可以很好的想到一种\(O(nm)\)的dp:状态:\(dp_{i,j}\)为搜到第\(i\)个,最后一个数是\(j\)的方案数。转移:\(dp_{i,j}=\displaystyle\sum_{k|j,k\not=j}dp_{i-1,k}\)当然这是会超时的。我们换一种思路,我们先枚举最后一个数,再计算方案数。这有个好处,我们缩小......
  • 在上一操作期间遇到问题: “Debug|AnyCPU”配置中 "TargetFrameworkMoniker" 和 "NuGe
    最近在学习avalonia的源代码,突然间visualstudio2022提示很多好多类似的红色错误在上部菜单下方xxx项目在上一操作期间遇到问题:“Debug|AnyCPU”配置中"TargetFrameworkMoniker"和"NuGetTargetMoniker"属性的值均为空。此配置将影响NuGet还原,这可能导致还原和生成错误......
  • [903] Concatenate (merge) multiple dictionaries in Python
    Toconcatenate(merge)multipledictionariesinPython,youcanusevariousmethodsdependingonyourPythonversionandpreferences.Herearesomecommonapproaches:1.Usingtheupdate()Method:Youcanusetheupdate()methodofdictionariestomergeo......
  • D. Prefix Permutation Sums
    D.PrefixPermutationSums吐槽:读题不仔细,还以为原数组的取值是任意的,最后看题解的时候才发现取值在[1,n],当时因为看不懂直接跳过了题意:给你一个缺了一个的前缀和数组,让你判断是否存在原数组,取值[1,n],每个数只存在一次可以分类讨论1缺少最后一个前缀和2缺少前面的前缀和......
  • cmake之link_libraries 和 target_link_libraries区别
    在cmake语法中,link_libraries和target_link_libraries是很重要的两个链接库的方式,虽然写法上很相似,但是功能上有很大区别:link_libraries用来链接静态库,target_link_libraries用来链接导入库,即按照头文件+.lib(动态库导入库)+.dll(动态库)方式隐式调用动态库的.lib导入......
  • [vue] event.currentTarget和 event.target的区别
    <divclass="aaa"@click="handleClick($event)"><divclass="bbb"></div></div>handleClick(event){//是你绑定事件的元素aaaconsole.log(event.currentTarget);//是你当前点击的元素bbbconsole.log(event.target);......
  • VScode中下载了插件但是无法找到SSH Target连接服务器的解决方法(CANNOT find SSH Targ
    VSCode版本vscodeversion:(version1.82)已下载扩展installedextensions:Remote-SSHv0.106.4Remote-SSH:EditingConfigurationFilesv0.86.0RemoteDevelopmentv0.24.0WSLv0.81.3几天前我从pycharm转战vscode,在连接服务器时遇到了一些问题。根据一些较为古早的......
  • 解决Android studio 更新到2022.3版本后,一直卡在waiting for target device to come o
    解决Androidstudio更新到2022.3.1patch1之后卡在waitingfortargetdevicetocomeonline的问题1.现象在发布一个app的时候,每次走到waitingforalltargetdevicestocomeonline之后,就没有后续了,模拟器没有调起来,更不用谈后续的install。2.原因暂时不明3.解决方法......
  • Go - Using Multiple Versions of the Same Dependent Packages
    Problem: Youwanttousemultipleversionsofthesamedependentpackagesinyourcode.Solution: Usethereplacedirectiveinthego.modfiletorenameyourpackage.Thoughitmightseemlikeaverynicherequirement,thereissometimesaneedtobeabl......
  • [891] Combine multiple dictionaries in Python
    TocombinemultipledictionariesinPython,youcanuseanyofthemethodsmentionedearlierforcombiningtwodictionaries.Youcanrepeatedlyapplythesemethodstomergemultipledictionariesintoone.Here'showyoucandoit:Usingtheupdate()......