← 开发笔记

Java 等差数列:乘法前先提升类型

从 x 开始的 n 个值是 x × 1 到 x × n。结果可能超出 int 范围,因此结果数组和乘法运算本身都必须使用 long。

题目规定 x 的范围为 -10,000,000 到 10,000,000,n 为 1 到 1,000。因此,最后一项的绝对值可能达到 10,000,000,000,需要使用 long 数组。

处理流程

把从零开始的下标转换为项号,在乘法前将 x 提升为 long,再按顺序收集。

把从零开始的下标转换为项号,在乘法前将 x 提升为 long,再按顺序收集。

把下标转换为项号

将完整类保存为 Solution.java。原文中的代码已按 Java 11 目标编译,并在 JDK 17 上执行。

import java.util.stream.IntStream;

public class Solution {
    public long[] solution(int x, int n) {
        return IntStream.range(0, n)
                .mapToLong(i -> (long) x * (i + 1))
                .toArray();
    }
}

IntStream.range(0, n)生成 0 到 n-1 的下标。乘以 i + 1 后,第一项是 x,最后一项是 x×n。从 x×0 开始会改变题目要求的数列。

x n 结果
2 5 [2,4,6,8,10]
-4 2 [-4,-8]
0 3 [0,0,0]

负的 x 生成递减的值,x=0 则只生成零。必须保留项的顺序;这不是排序问题。

仅使用 mapToLong 不能保护乘法结果

即使在 mapToLong 内,先计算 x * (i + 1) 仍会执行 int 乘法,因为两个操作数都是 int。(long) (x * (i + 1)) 也在溢出发生后才转换类型。

示例通过 (long) x * (i + 1) 先提升一个操作数的类型。原文的检查比较了正、负边界下分别以 10,000,000,000 和 -10,000,000,000 结尾的完整参考数组。较小的正、负和零输入也与通过重复加法构造的数组进行了比较。

时间复杂度为 O(n),包含返回数组的空间复杂度为 O(n)。实现遵循题目约束,没有对数列长度或任意 API 输入进行通用验证。

对于在给定范围内可用 int 完成的计算,可对照带符号求和和数组内积。Java 编程练习指南将数组运算与字符串、集合练习连接起来。

讨论