• 23. 霍纳法则(多项式求值快速算法)


    一. 概念引入

    1.定义

    (1)x 的 n 次多项式: P(x) = anxn + an-1xn-1 + ... + a1x + a0。(其中 x 是底数, n 是指数, ai 是每一项前面的系数, 0 ≤ i ≤ n ,并且最高次项前面的系数不为 0 )

    2. 实例分析

    (1)求 xn 的方法:

    xn = x · x · … · x (共 n 个 x ),显然,式子中执行了 n - 1 次乘法。

    取 x = 2, n = 3 时,该项为 23 = 2 × 2 × 2,可以看出,执行了 2 次乘法。

    (2)求 x 的 n 次多项式的方法:

    假设有多项式 P(x) = anxn + an-1xn-1 + ... + a1x + a0。先看第一项 anxn ,其中 xn 执行了 n - 1 次乘法,再与 an 相乘,共执行 n 次乘法。其余各项同理。

    取 x = 2, n = 4, 系数为 1 时, P(2) = 24 + 23 + 22 + 21 + 1

    二. 多项式求值常规算法

    继续以上例来说明问题:取 x = 2, n = 4, 系数为 1 时, P(2) =24  + 23 + 22 + 21 + 1。

    当我们用正常思路去计算,即先算第一项,再算第二项,直到算出每项结果,最后将各项结果相加。先算第一项: 2 × 2 × 2 × 2 ,再算第二项: 2 × 2 × 2, 再算第三项: 2 × 2。该算法的时间复杂度是 O(n2)。我们可以发现,其中有很多重复步骤。第一项已经做完了大部分工作,其余项为什么要把第一项的劳动成果弃之不用呢?

    三. 霍纳法则

    霍纳将多项式进行变形:P(x) = a3x3 + a3x2 + a1x + a0  → P(x) = x ( x ( x ( a3 ) + a2 ) + a1 ) + a0 ,这样执行多项式求值,每一次的结果都能得到充分的利用,不难看出,霍纳算法的时间复杂度是 O( n )

    四. 代码实现

    1. 常规算法

    这里我手动实现了一个函数 cal_power,用于计算 x 的 n 次方。

     1 int cal_power(int x, int n) {
     2     int product = x;
     3     for (int i = 0; i < n - 1; ++i) {
     4         product *= x;
     5     }
     6 
     7     return product;
     8 }
     9 
    10 int cal_ploy (vector<int> &coefficient, int x, int n) {
    11     int sum = coefficient[ n ];
    12     for (int i = 0; i < n; ++i) {
    13         int item = coefficient[ i ] * cal_power(x, n - i);
    14         sum += item;
    15     }
    16 
    17     return sum;
    18 }

    2.霍纳法则 

    1 int honour_rule(vector<int> &coefficient, int x, int n) {
    2     int sum = coefficient[0];
    3     for (int i = 1; i <= n; ++i) {
    4         sum = x * sum + coefficient[i];
    5     }
    6 
    7     return sum;
    8 }

    3.测试

     1 int main() {
     2     int x, n, result;
     3     cout << "Enter x, n : ";
     4     cin >> x >> n;
     5     vector<int> coefficients;
     6 
     7     for (int i = 0; i <= n; ++i) {
     8         int current_num;
     9         cout << "coefficient " << (i + 1) << " : ";
    10         cin >> current_num;
    11         coefficients.push_back(current_num);
    12     }
    13 
    14     result = cal_ploy(coefficients, x, n);
    15     cout << "regular sum = " << result << endl;
    16 
    17     result = honour_rule(coefficients, x, n);
    18     cout << "honour rule sum = " << result << endl;
    19 
    20     cout << "Done." << endl;
    21 
    22     return 0;
    23 }

    其中需要说明几点:

    第一,代码中没有错误处理,边界检查,默认输入没有问题,这样做只是为了清楚地说明算法思路,略去了算法无关的内容,但是实际操作中,这些代码必不可少。

    第二,用 vector 来保存系数,在输入时,按照表达式的系数顺序输入即可,不用从后往前输入。

  • 相关阅读:
    266. Palindrome Permutation
    265. Paint House II
    264. Ugly Number II
    263. Ugly Number
    261. Graph Valid Tree
    260. Single Number III
    259. 3Sum Smaller
    pthon 批量压缩当前目录,子目录下图片
    不小心打开了N多的压缩文件窗口,一句命令就搞定!
    # Writing your-first Django-app-part 4-simple-form
  • 原文地址:https://www.cnblogs.com/Hello-Nolan/p/13168149.html
Copyright © 2020-2023  润新知