leetcode
leetcode 2601 ~ 2650
查找总价格为目标值的两个商品

查找总价格为目标值的两个商品

难度:

标签:

题目描述

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

代码结果

运行时间: 116 ms, 内存: 25.5 MB


/*
题目思路:
我们使用Java Stream来实现这个题目,步骤如下:
1. 将价格数组转换为一个List,以便使用Stream API。
2. 创建一个哈希表来存储已经遍历过的价格。
3. 使用Stream的forEach方法遍历价格数组。
4. 对于每个价格,计算其补数(即 target - 价格)。
5. 检查补数是否在哈希表中存在,如果存在则输出这两个价格并终止遍历。
6. 如果遍历完数组还没有找到符合条件的两个价格,则返回空数组。
*/
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class TwoSumStream {
    public int[] findTwoSum(int[] price, int target) {
        Map<Integer, Integer> priceMap = new HashMap<>();
        List<Integer> priceList = IntStream.of(price).boxed().collect(Collectors.toList());
        int[] result = new int[1];
        priceList.stream().forEach(p -> {
            int complement = target - p;
            if (priceMap.containsKey(complement)) {
                result[0] = complement;
                result[1] = p;
            } else {
                priceMap.put(p, p);
            }
        });
        return result[0] == 0 ? new int[0] : new int[]{result[0], result[1]};
    }
}

解释

方法:

题解采用了双指针技巧,通过设置一个指针i指向数组的起始位置,另一个指针j指向数组的末尾位置。通过比较两个指针所指元素的和与目标值的关系来调整指针的位置:如果两数之和大于目标值,则将右侧指针向左移动以减小和的值;如果两数之和小于目标值,则将左侧指针向右移动以增大和的值;如果两数之和等于目标值,就返回这两个元素。由于数组是有序的,这种方法能有效地找到目标组合。

时间复杂度:

O(n)

空间复杂度:

O(1)

代码细节讲解

🦆
在题解中提到双指针从两端开始移动,为什么这种方法仅适用于已经排序的数组?
在已排序的数组中,双指针从两端开始移动可以有效地利用数组的有序性确定指针的移动方向。一个指针从左端开始,代表最小值区域,另一个从右端开始,代表最大值区域。如果两指针指向值的和小于目标值,说明需要增大和的值,因此移动左侧指针向右以获取一个更大的数;如果和大于目标值,需要减小和的值,因此移动右侧指针向左以获取一个更小的数。如果数组未排序,这样的移动就无法保证正确调整和的大小,因为移动任一指针的结果对和的影响是不确定的。
🦆
如果在处理过程中i和j指向的元素相同,即nums[i] == nums[j],这种情况下算法是否还能正确处理,尤其是当target等于nums[i]*2时?
在这种算法中,当i和j指向同一元素时,即nums[i] == nums[j],实际上是不可能的,因为算法的循环条件是i < j,即两指针不会指向同一位置。因此,如果目标值target等于nums[i]*2,只有当数组中存在两个相同的值时,这两个值分别被i和j指向才能正确返回。如果数组中没有重复的符合条件的元素,或者没有两个不同位置的元素其值乘以2等于target,则算法不会找到这样的一对数。
🦆
题解里提及‘如果和大于目标值,则将右侧指针向左移动’,这种操作是否有可能错过正确的组合?请解释其逻辑。
在已排序的数组中,这种操作不会错过正确的组合。因为当和大于目标值时,为了减小和的值,必须减少当前的和。在数组已排序的情况下,右指针向左移动意味着取一个较小的数,从而减小和的总值。如果向左移动右指针而错过了正确的组合,那意味着存在比当前右指针还要大的数与左指针指向的数相加等于目标值,这与数组排序的性质相矛盾。
🦆
代码中的while循环条件为`i < j`,如果数组中仅有两个元素且这两个元素的和正好是target,这种边界情况是否有正确处理?
是的,这种边界情况已经被正确处理。当数组仅有两个元素时,i初始化为0,j初始化为1,即i和j分别指向这两个元素。因为条件i < j成立,循环会执行。在循环内部,如果这两个元素的和等于目标值,那么这对元素将被返回。因此,即使是只有两个元素的数组,只要它们的和符合目标值,算法也能正确返回这两个元素。

相关问题