2

这是我将形式的两个多项式相乘的方法an*x^n + an-1*x^n-1 + ... + a1*x + a0。每个Term对象都有两个字段:double coefficientint powerPolynomial通过将项存储在 中来表示多项式ArrayList<Term>。乘法的当前实现是 O(n^2)。关于如何使其更快的任何想法或提示?

public Polynomial multiply(Polynomial P2) {
    PolynomialImp result = new PolynomialImp();
    for (Term currentThisTerm : this.terms)
    {
        for (Term currentP2Term : ((PolynomialImp) P2).terms)
        {
            result.addTerm(new TermImp(currentThisTerm.getCoefficient()*currentP2Term.getCoefficient(), currentThisTerm.getExponent() + currentP2Term.getExponent()));
        }
    }
    //Sort polynomial in decreasing exponent order
    return result.sort();
}

如果需要,下面是 addTerm 方法:

private void addTerm(Term nextTerm)
{
    for (int i = 0; i < this.terms.size(); i++)
    {
        if (this.terms.get(i).getExponent() == nextTerm.getExponent())
        {
            //Add the coefficients if the current term has the same exponent as a term that is already in the polynomial.
            //This preserves the sorting of the polynomial except during multiply.
            this.terms.set(i, new TermImp(this.terms.get(i).getCoefficient() + nextTerm.getCoefficient(), this.terms.get(i).getExponent()));
            return;
        }
    }
    //Avoid adding zeros to the polynomial.
    if (nextTerm.getCoefficient() != 0)
        this.terms.add(nextTerm);
}
4

3 回答 3

5

这就是我可能实现此功能的方式

public class Polynomial {
    private final double[] coeff;

    public Polynomial(double... coeff) {
        this.coeff = coeff;
    }

    @Override
    public String toString() {
        return Arrays.toString(coeff);
    }

    public Polynomial multiply(Polynomial polynomial) {
        int totalLength = coeff.length + polynomial.coeff.length - 1;
        double[] result = new double[totalLength];
        for (int i = 0; i < coeff.length; i++)
            for (int j = 0; j < polynomial.coeff.length; j++) {
                result[i + j] += coeff[i] * polynomial.coeff[j];
            }
        return new Polynomial(result);
    }

    public static void main(String... args) {
        Polynomial p1 = new Polynomial(1, 2, 3);
        System.out.println(p1 + "^2 =" + p1.multiply(p1));
        Polynomial p2 = new Polynomial(3, -1, -1);
        System.out.println(p1 + "*" + p2 + "=" + p1.multiply(p2));
    }
}

印刷

[1.0, 2.0, 3.0]^2 =[1.0, 4.0, 10.0, 12.0, 9.0]
[1.0, 2.0, 3.0]*[3.0, -1.0, -1.0]=[3.0, 5.0, 6.0, -5.0, -3.0]
于 2012-10-04T16:39:16.817 回答
1

可能使该算法变慢的原因是创建了 n^2 个 TermImp 对象。在 C++ 中,这应该不是问题,因为您将在堆栈上创建对象并按值传递。我的理解是,在 Java 中你没有这个选项:你必须接受创建对象的开销,然后通过引用传递。

每次乘以一个术语时都创建一个新对象似乎效率低下。不能直接消除吗?

您可以考虑更改 addTerm 方法以接受系数和指数作为双精度/整数参数。

对于大的 n,该算法仍然是 O(n^2),但它仍然应该加快很多。

您可以考虑的另一件事是使用 for 循环而不是迭代器,因为迭代器还涉及创建新对象……尽管 O(n) 不是那么重要。

于 2012-10-04T16:48:29.447 回答
0

您有一个主要的低效率:您将术语存储在看似无序列的列表中。您应该修改您的代码,以便 terms.get(n) 返回带有 x^n 的术语。然后,您无需在 addTerm 方法中搜索 terms 变量。

为此,您必须更新所有修改术语的代码以保持术语有序。

乘法方法本身看起来很高效,我认为它不能再优化了。

于 2012-10-04T16:33:49.953 回答