首页 > 编程语言 >得到杨辉三角某行数据算法优化

得到杨辉三角某行数据算法优化

时间:2024-05-28 12:29:04浏览次数:28  
标签:index rows int long factorial 算法 杨辉三角 优化 row

引导

注意:最佳方案在文章最后,中间为思考过程

最朴实的方法:

       

        我们将这些数据的第一行称作为杨辉三角的第0行,每行的第一个数据称作为第0个数据,以方便之后的算法

        根据杨辉三角的基础性质,即 第row 行 index个数据等于第row-1行第index 数据与 row-1 第index-1 两个数据的和 即 T[row][index]=T[row-1][index]+T[row-1][index-1]

        由此我们可以得到杨辉三角每一行的数据

        #杨辉三角 <-这题可由此方式解决

class Solution {
public:
    vector<vector<int>> generate(int numRows) {
        vector<vector<int>> ans(numRows);
        for(int i=0;i<numRows;i++){
            ans[i].resize(i+1);
            ans[i][0]=1;ans[i][i]=1;
            for(int j=1;j<i;j++){
                ans[i][j]=ans[i-1][j]+ans[i-1][j-1];
            }
        }
        return ans;
    }
};

 

但是若是只想要某一行的数据,这种方式就太过浪费时间

例如#杨辉三角II <-此题就要求在时间复杂度O(n)的情况下解决问题

        那么根据我们高中所学,杨辉三角中的每一项都可看作二项式系数的一项

        例如第m行第n个数据是C(m,n) 即(m*(m-1)*(m-2)*...(m-n+1))/(n!)

        其中C(m,n)中我们可用(factoriol是阶乘的意思)factoriol(m)/(factorial(m-n)*factorial(n))表示

由此写出代码

class Solution {
public:
    long long factorial(int n){
        long long ans=1;
        for(int i=2;i<=n;i++){
            ans*=i;
        }return ans;
    }
    long long c(int rows,int index){
        if(index>rows/2){return c(rows,rows-index);}
//此处利用排列组合的性质c(m,n)==c(m,m-n)以优化算法
        long long numerator=factorial(rows);//分子
        long long denominator=factorial(index)*factorial(rows-index);//分母
        return numerator/denominator;
    }
    vector<int> getRow(int rowIndex){
        vector<int> ans(rowIndex+1);
        ans[0]=1;ans[rowIndex]=1;
        for(int i=1;i<rowIndex;i++){
            ans[i]=c(rowIndex,i);
        }
        return ans;
    }
};

不过这个代码无法通过测试,原因是:

数据超出了long long 的范围因此报错

分析原因我们可以发现阶乘会使得数据大得多

因此我们回归C(m,n)最原本的计算方法即:C(m,n) ==(m*(m-1)*(m-2)*...(m-n+1))/(n!)

得出代码:


    long long c(int rows,int index){
        if(index>rows/2){return c(rows,rows-index);}
        long long numerator=1;
        long long denominator=factorial(index);
        for(int i=0;i<index;i++){
            numerator*=rows-i;
        }
        return numerator/denominator;
    }

但是运行出来后仍然会由数据溢出的报错,因此我们可以在计算过程中提前对分子与分母进行约分:因为分子分母都是连续的整数相乘,所以他们会有大量的2或者3 的公因数

    long long c(int rows,int index){
        if(index>rows/2){return c(rows,rows-index);}
        long long numerator=1;
        long long denominator=factorial(index);
        for(int i=0;i<index;i++){
            numerator*=rows-i;
            while(numerator%2==0&&denominator%2==0){
                numerator/=2;
                denominator/=2;
            }
        }
        return numerator/denominator;
    }

运行得出的结果完美

 再看一下官方题解

class Solution {
public:
    vector<int> getRow(int rowIndex) {
        vector<int> row(rowIndex + 1);
        row[0] = 1;
        for (int i = 1; i <= rowIndex; ++i) {
            row[i] = 1LL * row[i - 1] * (rowIndex - i + 1) / i;
        }
        return row;
    }
};

比我的简单的多。。

        看玩题解之后恍然大悟,我们可以根据前项推出后向的和,从而越过求阶乘的步骤,不仅简单,速度还更快,其递推公式是:C(m,n)=C(m,n-1)*((n-m+1)/n)

推理过程如下:C(m,n-1)==(m*(m-1)*(m-2)*...(m-n+2))/((n-1)!)

                         C(m,n) ==(m*(m-1)*(m-2)*...(m-n+2)*(m-n+1))/(n!)

                                     ==C(m,n-1)*(m-n+1)/n

标签:index,rows,int,long,factorial,算法,杨辉三角,优化,row
From: https://blog.csdn.net/qq_34037296/article/details/139262042

相关文章

  • 力扣算法之1050. 合作过至少三次的演员和导演
    题解actor_id和director_id,类似一个坐标,只要出现三次或者三次以上就打印出来我的解SELECTactor_id,director_idFROMActorDirectorGROUPBYactor_id,director_idHAVINGCOUNT(1)>=3我的解注解同时分组,两个出现次数大于等于3的就是符合的,看了下,其他的思路和这个......
  • 锂电池寿命预测 | Matlab基于ALO-SVR蚁狮优化支持向量回归的锂离子电池剩余寿命预测
    目录预测效果基本介绍程序设计参考资料预测效果基本介绍【锂电池剩余寿命RUL预测案例】基于蚁狮优化和支持向量回归的锂离子电池剩余寿命预测(完整源码和数据)1、提取NASA数据集的电池容量,以历史容量作为输入,采用迭代预测的方法对未来的容量进行预测:2......
  • Redis如何进行内存优化
    控制key的数量。当使用Redis存储大量数据时,通常会存在大量键,过多的键同样会消耗大量内存。Redis本质是一个数据结构服务器,它为我们提供多种数据结构,如hash,list,set,zset等结构。使用Redis时不要进入一个误区,大量使用get/set这样的API,把Redis当成Memcached使用。对于存储相同的......
  • .NET8极致性能优化AOT
    前言.NET8对于性能的优化是方方面面的,所以AOT预编译机器码也是不例外的。本篇来看下对于AOT的优化。原文:.NET8极致性能优化AOT详述首先明确一个概念,.NET里面的AOT它是原生的。什么意思呢?也就是说通过ILC编译器(AOT编译器,参考:.Net7新编译器ILC简析)编译出来的代码是各个平......
  • 代码随想录算法训练营第第20天 | 654.最大二叉树 、617.合并二叉树 、700.二叉搜索
    654.最大二叉树又是构造二叉树,昨天大家刚刚做完中序后序确定二叉树,今天做这个应该会容易一些,先看视频,好好体会一下为什么构造二叉树都是前序遍历题目链接/文章讲解:https://programmercarl.com/0654.最大二叉树.html视频讲解:https://www.bilibili.com/video/BV1MG411G7ox......
  • 代码随想录算法训练营第三十七天 | 860.柠檬水找零、406.根据身高重建队列、452.用最
    目录860.柠檬水找零思路代码 406.根据身高重建队列思路代码452.用最少数量的箭引爆气球思路代码860.柠檬水找零本题看上好像挺难,其实挺简单的,大家先尝试自己做一做。代码随想录思路    这题还有什么难不难的,这道题不是非常经典的入门题吗。......
  • 算法导论,矩阵链乘法(动态规划)
    直入主题,5.27学的矩阵链相乘(动态规划)题目理解:        1.原题                要求:对A1,A2,A3......An进行矩阵的乘法(线性代数的基础知识),求通过添加括号,以达到的最小乘法次数    2.题目理解        乘法:由于矩阵乘法的结合......
  • 代码随想录算法训练营第五天|242(有效的字母异位词),349(两个数组的交集),202(快乐数)
    哈希C#常用的数据结构:[]Array,ArrayList数组和动态数组List集合HashSet哈希集合(无重复值)HashTable哈希表(obj,obj的键值对)Dictionary<T,T>泛型的哈希表什么时候考虑Hash数据结构?需要高效的判断一个值是否存在在一个容器中时。容器不允许重复值(HashSet或哈希表的......
  • 关于学生信息管理系统的优化
    关于学生信息管理系统的优化优化1:更改引导用户创建数据库的方案FILE*fp=fopen(file_name,"r");chars[100];intn;if(fp==NULL){printf("未检测到数据库,请问是否创建(y/n)?");scanf("%s",s);printf("\n");......
  • 【算法】合并k个已排序的链表
    ✨题目链接:NC51合并k个已排序的链表✨题目描述 合并k 个升序的链表并将结果作为一个升序的链表返回其头节点。数据范围:节点总数 0≤......