← 开发笔记

Java 数组点积:IntStream 与整数范围

两个数组的点积,是相同下标处元素乘积的总和。先把元素相加,或把两个数组各自的总和相乘,得到的是不同的结果。

这道练习题提供两个长度相同的整数数组,长度为 1–1000,元素取值为 -1000 到 1000。在这些限制下,结果使用 int 即可。

处理流程

将每个共同下标映射为对应元素的乘积,再将这些乘积求和。题目的取值范围不会超出 int。

将每个共同下标映射为对应元素的乘积,再将这些乘积求和。题目的取值范围不会超出 int。

按下标计算乘积并求和

将以下完整类保存为 Solution.java。它已按 Java 11 编译,并以输入数组长度相同为前提。

import java.util.stream.IntStream;

public class Solution {
    public int solution(int[] a, int[] b) {
        return IntStream.range(0, a.length)
                .map(i -> a[i] * b[i])
                .sum();
    }
}

IntStream.range(0, a.length)不包含结束下标。将每个下标映射为 a[i] * b[i],再通过 sum() 合并乘积。这个基本类型下标流不需要先构建装箱后的 Integer 列表。

对于 [1, 2, 3, 4] 和 [-3, -1, 0, 2],各项乘积为 -3, -2, 0, 8,结果是 3。必须保留负号:取绝对值会改变点积。

何时使用 int 就足够

每个乘积的绝对值最多为 1000000,最多有 1000 项。因此,总和的绝对值不超过 1000000000,处于 Java 的 int 范围内。边界检查也覆盖了 1000 项全部达到最大正值或最大负值的情况。

对于更大的输入,只把累加器改为 long 可能仍然不够。(long) (a[i] * b[i]) 是在 int 乘法已经溢出后才转换类型。应当在乘法之前使用 (long) a[i] * b[i] 提升类型,同时将求和与返回类型设计为 long。这里提交的方法仍遵守题目要求的 int 约定。

时间复杂度为 O(n),额外空间复杂度为 O(1)。这不是一个会校验数组长度不等、数组为 null 或元素超出范围等情况的通用向量库。

要把固定的英文数字单词转换为整数,请参阅数字单词与数字字符串。

讨论