leetcode
leetcode 1251 ~ 1300
多次求和构造目标数组

多次求和构造目标数组

难度:

标签:

题目描述

代码结果

运行时间: 30 ms, 内存: 21.1 MB


/*
 * 思路:
 * 使用Stream API来处理目标数组。虽然Stream在处理复杂逻辑时不如常规方法直观,但我们可以使用集合操作来实现逻辑。
 * 1. 从目标数组中找到最大的元素,这个元素是由前一步的数组和构成的。
 * 2. 将该元素减去数组和的其余部分,得到上一步的元素。
 * 3. 如果新的元素为0或负数,则不可能构造目标数组,返回false。
 * 4. 继续重复上述步骤,直到所有元素都变成1为止。
 */

import java.util.*;
import java.util.stream.Collectors;

public class SolutionStream {
    public boolean isPossible(int[] target) {
        if (target.length == 1) {
            return target[0] == 1;
        }
        PriorityQueue<Integer> pq = new PriorityQueue<>(Comparator.reverseOrder());
        long sum = Arrays.stream(target).asLongStream().sum();
        pq.addAll(Arrays.stream(target).boxed().collect(Collectors.toList()));
        while (true) {
            int max = pq.poll();
            sum -= max;
            if (max == 1 || sum == 1) {
                return true;
            }
            if (max < sum || sum == 0 || max % sum == 0) {
                return false;
            }
            max %= sum;
            sum += max;
            pq.offer(max);
        }
    }
}

解释

方法:

题解使用了反向操作的思路,即从target数组反推回初始数组,看是否所有元素均能变为1。主要思路是使用最大堆(通过存储负数来使用Python的最小堆实现最大堆的效果),每次从堆中取出当前最大的元素,计算这个元素与其他元素总和的差,即是上一次操作后该位置的值。如果在任何时刻,最大元素值减去其他元素的总和小于1,说明无法通过加法操作得到该值,返回False。继续这个过程,直到所有元素变为1。这个方法利用了每次操作对数组的最大值影响最大的特性,从而反向模拟得到是否可行。

时间复杂度:

O(n log m) ,其中n是target数组的长度,m是target数组中元素的最大值。

空间复杂度:

O(n)

代码细节讲解

🦆
在反向操作中,为什么选择每次都从最大的元素开始处理?
在反向操作中选择从最大元素开始处理的原因是因为在多次求和的操作过程中,每次操作的结果主要受到当前数组中最大值的影响。从最大值开始反推可以更直接地模拟回溯到初始数组的过程。如果最大值可以通过减去其他元素的总和的方式逐步减小到1,那么这种反推是成功的。另外,这样的操作还可以有效减少计算次数,因为最大值的变化直接决定了数组是否可以继续进行反推。
🦆
算法中提到的`ceil((p - a) / rest)`计算是如何确定的?请解释其逻辑和作用。
在算法中,`ceil((p - a) / rest)`的计算用来确定将最大值p减小至小于或等于次大值a所需的最小次数。这里的rest代表除了最大值p之外其他所有元素的总和。由于每次操作都是将最大值p减去rest,所以,为了使p尽可能快地减到a或者更小,需要计算p减去rest的次数。使用`ceil`函数是因为即使除法结果为非整数,也需要将次数向上取整,确保最大值p在足够的操作次数后能够小于或等于a。这个计算对于加速算法进程和确保算法的正确逻辑非常关键。
🦆
如果最大元素减去其他元素的总和小于1,则返回False,这一步为什么是必要的,它在算法中起到什么作用?
这一步是检查在反向操作过程中是否存在无法通过加法操作得到当前数组的情况。具体来说,如果在任何时刻,从堆中取出的当前最大元素值减去其他元素的总和小于1,说明这个最大元素无法通过之前的加法操作形成,因为每次操作至少增加1。这是一个基本的验证步骤,用来确保所有元素都可以有效地通过反向操作减小到1。如果不满足这一条件,则说明目标数组不可能通过一系列加法操作从全1数组开始构造得到,算法应当返回False。
🦆
在处理过程中,当最大值和第二大值相等时,为什么判断为无法进行操作,即返回False?
当最大值和第二大值相等时,判断为无法进行操作并返回False是因为在这种情况下,无法通过正常的加法操作区分这两个值。在正常的多次求和操作中,每一次操作都会使得某一个元素(最大元素)显著增加,而其他元素相对较小或不变。如果两个最大值相等,说明没有任何单次操作可以使一个元素成为独立的最大值,从而违反了这种操作逻辑。因此,这种情况下目标数组不能通过从全1数组的多次求和操作得到。

相关问题