leetcode
leetcode 2901 ~ 2950
采购方案

采购方案

难度:

标签:

题目描述

English description is not available for the problem. Please switch to Chinese.

代码结果

运行时间: 136 ms, 内存: 26.7 MB


/* 
 * 思路:
 * 1. 对数组进行排序。
 * 2. 使用双指针方法,通过Stream API的简化处理。
 * 3. 将双指针的逻辑封装在一个for循环中。
 * 4. 若两数之和小于等于目标值,则将符合条件的配对计数加上,左指针右移。
 * 5. 否则右指针左移。
 * 6. 使用 1e9 + 7 对结果取模。
 */

import java.util.Arrays;
import java.util.stream.IntStream;

public class Solution {
    public int purchasePlans(int[] nums, int target) {
        Arrays.sort(nums);
        final int MOD = 1000000007;
        long count = IntStream.range(0, nums.length)
                .mapToLong(left -> {
                    int right = nums.length - 1;
                    long localCount = 0;
                    while (left < right) {
                        if (nums[left] + nums[right] <= target) {
                            localCount += right - left;
                            localCount %= MOD;
                            left++;
                        } else {
                            right--;
                        }
                    }
                    return localCount;
                })
                .sum() % MOD;

        return (int) count;
    }
}

解释

方法:

此题解使用了双指针技巧。首先,将数组排序,然后使用两个指针,一个指向数组的开始(左指针),另一个指向数组的末尾(右指针)。左指针代表的是较小的数,右指针代表的是较大的数。不断检查两个指针所指的数之和是否小于等于目标值 target。如果是,则所有介于左指针和右指针之间的组合都满足条件(因为数组是排序的,所以右指针左边的任何一个数字加上左指针的数字都会小于等于target),于是将这些组合计入答案中。然后移动左指针向右寻找新的组合。如果两数之和大于 target,则移动右指针向左以减小数值之和。这个过程持续到左指针不再小于右指针。

时间复杂度:

O(n log n)

空间复杂度:

O(log n)

代码细节讲解

🦆
为什么在这个问题中选择对数组进行排序是一个必要的步骤?
在这个问题中,对数组进行排序是必要的步骤,因为排序后数组的元素顺序保证了从小到大排列。这样在使用双指针策略时,可以有效地控制和调整指针以找到所有满足条件的组合。具体来说,当左指针指向的元素比较小,右指针指向的元素比较大时,如果这两个元素的和小于等于目标值,则左指针左侧的所有元素与右指针指向的元素的和也必然小于等于目标值。这种性质只有在数组有序的情况下才成立,因此排序是实现双指针策略的前提。
🦆
在双指针策略中,当左指针和右指针指向的元素之和小于等于目标时,为什么可以直接添加 `r - l` 到答案中,这种计算方式的正确性是如何保证的?
在双指针策略中,当两个指针指向的元素之和小于等于目标值时,由于数组是排序的,左指针(l)指向的是较小的元素,右指针(r)指向的是较大的元素。此时,位于左指针和右指针之间的任何一个元素与左指针指向的元素相加也一定小于等于目标值。因此,右指针到左指针之间的所有元素(包括右指针但不包括左指针),都可以与左指针组合构成有效的购买方案。这些组合的数量正是右指针与左指针的位置差(r - l),因此可以直接将这个值加到答案总数上。
🦆
如果在某些特殊情况下,所有的数组元素都非常接近 `target`,这种双指针方法的表现如何?会不会影响算法的效率?
如果数组中的所有元素都非常接近目标值 `target`,在使用双指针方法时可能会导致右指针频繁地向左移动以调整和值以适应目标条件。在这种情况下,即使每次调整后都可能发现较少的有效组合,整体算法效率依然保持较高,因为每一步右指针的移动都是有目的的—即寻找不超过目标值的元素组合。由于双指针策略本质上是线性扫描数组,因此算法的时间复杂度为O(n),即使在这种极端情况下,算法的效率仍然较高。

相关问题