leetcode
leetcode 2401 ~ 2450
使子序列的和等于目标的最少操作次数

使子序列的和等于目标的最少操作次数

难度:

标签:

题目描述

You are given a 0-indexed array nums consisting of non-negative powers of 2, and an integer target.

In one operation, you must apply the following changes to the array:

  • Choose any element of the array nums[i] such that nums[i] > 1.
  • Remove nums[i] from the array.
  • Add two occurrences of nums[i] / 2 to the end of nums.

Return the minimum number of operations you need to perform so that nums contains a subsequence whose elements sum to target. If it is impossible to obtain such a subsequence, return -1.

A subsequence is an array that can be derived from another array by deleting some or no elements without changing the order of the remaining elements.

 

Example 1:

Input: nums = [1,2,8], target = 7
Output: 1
Explanation: In the first operation, we choose element nums[2]. The array becomes equal to nums = [1,2,4,4].
At this stage, nums contains the subsequence [1,2,4] which sums up to 7.
It can be shown that there is no shorter sequence of operations that results in a subsequnce that sums up to 7.

Example 2:

Input: nums = [1,32,1,2], target = 12
Output: 2
Explanation: In the first operation, we choose element nums[1]. The array becomes equal to nums = [1,1,2,16,16].
In the second operation, we choose element nums[3]. The array becomes equal to nums = [1,1,2,16,8,8]
At this stage, nums contains the subsequence [1,1,2,8] which sums up to 12.
It can be shown that there is no shorter sequence of operations that results in a subsequence that sums up to 12.

Example 3:

Input: nums = [1,32,1], target = 35
Output: -1
Explanation: It can be shown that no sequence of operations results in a subsequence that sums up to 35.

 

Constraints:

  • 1 <= nums.length <= 1000
  • 1 <= nums[i] <= 230
  • nums consists only of non-negative powers of two.
  • 1 <= target < 231

代码结果

运行时间: 31 ms, 内存: 16.1 MB


/* 
 * 题目思路: 
 * 1. 使用 Java Stream API 处理数据。 
 * 2. 我们依然利用大顶堆 (PriorityQueue) 来管理当前的最大值。 
 * 3. 通过操作将大于 1 的元素拆分为两个小的元素,直到满足 target 或无法满足。
 */

import java.util.Arrays;
import java.util.PriorityQueue;

public class Solution {
    public int minOperations(int[] nums, int target) {
        PriorityQueue<Integer> pq = Arrays.stream(nums).boxed()
                .collect(Collectors.toCollection(() -> new PriorityQueue<>((a, b) -> b - a)));
        long sum = pq.stream().mapToLong(Integer::intValue).sum();
        if (sum < target) return -1;
        int operations = 0;
        while (target > 0) {
            int max = pq.poll();
            if (sum - max >= target) {
                sum -= max;
                continue;
            }
            if (max <= target) {
                target -= max;
            } else {
                pq.offer(max / 2);
                pq.offer(max / 2);
                operations++;
            }
            sum -= max;
        }
        return operations;
    }
}

解释

方法:

这道题目要求找到最少的操作次数,使得数组的一个子序列的和等于给定的target。首先,若nums数组中所有元素的和小于target,则直接返回-1,因为无论如何都无法达到target。接下来使用计数器cnt来统计nums中每个元素的出现次数。这里采用贪心的策略来尽量使用大的数。通过位运算来判断target的每个位是否需要当前的2的幂次元素。若需要而当前累积的和(acc)不足以提供该位的元素,则必须从更高位的元素中分裂出所需的更小元素,同时计数操作数。这个过程使用了两个循环:外层循环遍历可能的位数,内层循环处理分裂操作,直到找到可用的更大元素。最后,返回执行的总操作次数。

时间复杂度:

O(30) 或 O(log(target))

空间复杂度:

O(1)

代码细节讲解

🦆
为什么在算法中使用贪心策略来尽量使用大的数,这种策略是否总是能保证最少的操作次数?
使用大数的贪心策略是基于一个简单的观察:较大的数可以通过分裂变为多个较小的数,而较小的数不能组合为一个较大的数,所以尽早使用较大的数可以直接达到目标和的较高位,从而减少需要的操作次数。这种策略通常有效,但并不总是能保证最少的操作次数。在某些特定情况下,可能存在通过不同的分裂顺序或组合,使用较小数值资源达到更优的操作次数的情况。但在大多数情况下,使用较大的数能够有效减少操作次数。
🦆
在算法中,你是如何确保每次操作分裂的结果都是最优的?是否有可能存在分裂顺序不同导致操作次数更少的情况?
算法通过从最大可用元素开始分裂到所需的较小元素,以确保每次分裂都能尽可能多地解决紧迫的需求(即当前位的需求)。这种方法通常有效,但不一定总是最优的。确实存在特定的情况,分裂顺序的不同可能导致更少的操作次数。例如,在某些情况下,多次小范围的分裂可能比一次大范围的分裂导致较少的总操作次数。
🦆
算法中提到的外层循环是基于什么条件结束的?为什么选择`1 << i <= target`作为循环条件?
外层循环遍历所有可能的2的幂次元素,直到超过目标值`target`。选择`1 << i <= target`作为循环结束条件是因为,一旦2的幂次超过`target`,那么这个幂次的元素不可能对达到`target`有贡献。因此,以此为终止条件可以有效缩减不必要的计算和检查,专注于可能对满足目标值有直接贡献的元素。
🦆
在内层循环中,为什么直接跳过所有cnt[1 << j]为0的元素,这种跳过是否可能忽略了某些潜在的最优解?
内层循环中跳过cnt[1 << j]为0的元素,是因为这些元素在当前数组中不存在,因此不能用于当前的分裂操作。这种跳过方法并不会忽略潜在的最优解,因为无论如何,不存在的元素是无法参与到当前操作中的。此策略确保我们只关注实际可用的元素,从而在实际情况下达到最快解决问题的目的。

相关问题