算法期末整理(正在更新中)

news2025/2/28 2:48:32

一 算法概述

算法的概念

通俗地讲,算法是指解决问题的一种方法或一个过程。更严格地讲,算法是由若干条指令组成的有穷序列。

算法的性质

1.输入:有0个或多个由外部提供的量作为算法的输入。

2.输出:算法产生至少一个量作为输出

3.确定性:组成算法的每条指令是清晰的,无歧义的

4.有限性:算法中每条指令的执行次数是有限的,执行每条指令的时间也是有限的

程序与算法不同,程序是算法用某种程序设计语言的具体实现。程序可以不满足算法的性质4。例如,操作系统是一个在无限循环中执行的程序,因而不是一个算法。

描述算法的多种方式:自然语言方式,表格方式,伪代码等。

算法复杂性的高低体现在运行该算法所需要的计算机资源的多少上,所需资源越多,该算法的复杂性越高;反之,所需资源越少,该算法的复杂性越低。对计算机资源,最重要的是时间和空间资源。算法的复杂性有时间复杂性和空间复杂性。

算法复杂性是算法运行需要的计算机资源的量。算法复杂性只依赖于要解的问题的规模、算法的输入和算法本身的函数。

最坏情况、最好情况和平均情况下的时间复杂度从某个角度反映算法的效率,各有局限性,各有用处。可操作性最好且最有实际价值的是最坏情况下的时间复杂度

渐进符号

类似a=b

类似a<=b

类似a>=b 

类似a<b

 类似a<b

二 递归与分治策略

直接或间接地调用自身的算法称为递归算法。

阶乘函数可以递归的表示

int factorial(int n){
    if(n==0) 
        return 1;
    return n*factorial(n-1);
}

斐波那契数列可以递归的表示

int fibonacci(int n){
    if(n<=1)
        return 1;
    return fibonacci(n-1)+fabonacci(n-2);
}

排列问题

Perm(t){
    if(t==n)
        print
    else
        for i= t~n    //让每个都做一下排头,然后把剩下的全排列,就变成了一个全新的全排列。
             Swap(a[t],a[i]);
             Perm(t+1);
             Swap(a[t],a[i]);    //交换回来,以便下一次全排列
}   

 汉诺塔问题

void hanoi(int n,int a,int b,int c){//参数b是目标塔座,参数c是辅助塔座
    //hanoi函数的任务是把n个圆盘通过辅助c塔,从a塔全搬到目标b塔

    if(n>0){    //如果n=0,此时没有圆盘需要移动了
        hanoi(n-1,a,c,b);
        //如果想把第n个移到目标,就需要把上面的n-1个挪走到辅助塔座

        move(a,b);    // move 是一个圆盘从指定塔到另一个指定塔的移动
        //执行完hanoi(n-1,a,c,b)之后,就可以移动第n个到目标塔座了

        hanoi(n-1,c,b,a);
        //这个时候在把辅助塔座上n-1个放到目标塔座的第n个上面

        //此时n个汉诺塔的转移全部完成
    }
}

分治法的基本思想是将一个规模为n的问题分解为k个规模较小的子问题,这些子问题相互独立且与原问题相同。递归地解这些子问题,然后将各个子问题的解合并得到原问题的解。

二分搜索算法,采用分治策略,可在最坏情况下用O(logn)的时间完成搜索任务。

二分法的基本思想是,将n个元素分成个数大致相同的两半,取a[n/2]与x比较。如果x=a[n/2],则找到x,算法终止;如果x<a[n/2],则只在数组a的左半部继续搜索x;如果x>a[n/2],则只在数组a的右半部继续搜索x。

int BinarySearch(int a[],int x,int n){
    int left = 0;
    int right = n-1;

    while(left <= right){
    
    int mid=(left+right)/2;

    if(x==a[middle])
        return middle;
    if(x>a[middle])
        left=middle+1;
    else
        right=middle-1;
    }
    return -1;
}

Strassen 矩阵乘法 (分治法 + 减少矩阵乘法次数),矩阵乘法耗费的时间要比矩阵加(减)法耗费的时间多得多,要想改进矩阵乘法的计算时间复杂性,必须减少乘法运算。

棋盘覆盖问题

import java.util.Scanner;

public class Main {
    static int tile = 1;

    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        int k = sc.nextInt();
        int dr = sc.nextInt(); // 特殊方格所在行
        int dc = sc.nextInt(); // 特殊方格所在列

        int[][] Board = new int[(int) Math.pow(2, k)][(int) Math.pow(2, k)];
        Board[dr][dc]=0;
        ChessBoard(Board, 0, 0, dr, dc, Board.length);

        for (int i = 0; i < Board.length; i++) {
            for (int j = 0; j < Board.length; j++) {
                System.out.print(Board[i][j] + "\t");
            }
            System.out.println();
        }
    }
    public static void ChessBoard(int Board[][],int r_0,int c_0,int dr,int dc,int size){
        int s;
        int t;
        if (size==1) return;
        t=tile++;
        s=size/2;
        if (dr<=r_0+s-1 && dc<=c_0+s-1)
           ChessBoard(Board,r_0,c_0,dr,dc,s);
        else{
            Board[r_0+s-1][c_0+s-1]=t;
            ChessBoard(Board,r_0,c_0,r_0+s-1,c_0+s-1,s);
        }
        if (dr<=r_0+s-1 && dc>=c_0+s)
           ChessBoard(Board,r_0,c_0+s,dr,dc,s);
         else{
            Board[r_0+s-1][c_0+s]=t;
            ChessBoard(Board,r_0,c_0+s,r_0+s-1,c_0+s,s);
        }
         if (dr>=r_0+s && dc<c_0+s) //判断特殊方格是否在左下角子棋盘
           ChessBoard(Board,r_0+s,c_0,dr,dc,s);
         else //用t号骨牌覆盖右上角继续覆盖此子棋盘
         {
             Board[r_0 + s][c_0 + s - 1] = t;
             ChessBoard(Board, r_0 + s, c_0, r_0 + s, c_0 + s - 1, s);
         }
         if (dr>=r_0+s && dc>=c_0+s) //判断特殊方格是否在右下角子棋盘
           ChessBoard(Board,r_0+s,c_0+s,dr,dc,s);
         else //用t号骨牌覆盖左上角继续覆盖此子棋盘
         {
             Board[r_0+s][c_0+s]=t;
             ChessBoard(Board,r_0+s,c_0+s,r_0+s,c_0+s,s);
         }
    }
}

合并排序

合并排序算法是用分治策略实现对n个元素的进行排序的算法,其基本思想是:将待排序元素分成大小大致相同的两个子集合,分别对两个子集合进行排序,最终将排好的子集合合并成要求的排好序的集合。

MergeSort(int a[],int left,int right){    //left从左面指,right从右面指
//MergeSort的作用是给数组a做合并排序
    if(left<right){
        int i=(left+right)/2;    //i取中间
        MergeSort(a,left,i);     //对左面合并排序
        MergeSort(a,i+1,right);  //对右面合并排序
        Merge(a,b,left,i,right);    //排完序后合并到数组b,数组b是一个中间数组
        Copy(a,b,left,right);    //因为是给数组a排序,所以把数组b原封不动挪到数组a
    }
}

快速排序算法是基于分治策略的另一个排序算法。其基本思想是,对于输入的子数组a[p:r],按以下三个步骤进行排序。

分解:以a[p]为基准元素将a[p:r]划分成3段a[p:q-1],a[q]和a[q+1:r],使a[p:q-1]中的任何一个元素小于等于a[q],而a[q+1:r]中任何一个元素大于等于a[q]。下标q在划分过程中确定。

递归求解:通过递归调用快速排序算法,分别对a[p:q-1]和a[q+1:r]进行排序。

合并:由于对a[p:q-1]和a[q+1:r]的排序使就地进行的,因此在a[p:q-1]和a[q+1:r]都已排好的序后,不需要执行任何计算,a[p:r]则已排好序。

void QuickSort(int a[],int p,int r){
//QuickSort的功能是对a数组下标p到r的部分进行快速排序
    if(p<r){    //当p=r,就要排的数了
        int q=Partition(a,p,r); 
        //取下标q,从而分成左右两部分
        //比a[q]小的放左边,大的放右边

        QuickSort(a,p,q-1);        //对左边的进行排序
        QuickSort(a,q+1,r);        //对右边的进行排序
    }

    不停的递归调用,拆成两部分,直到要排的只有一个数(或不存在)就停止
}

三 动态规划

动态规划的基本要素:最优子结构性质,重叠子问题性质

动态规划算法与分治法类似,其基本思想是将待求解问题分解成若干子问题,先求解子问题,再结合这些子问题的解得到原问题的解。与分治法不同的是,适合用动态规划求解的问题经分解得到的子问题往往不是独立的。若用分治法来解这类问题,则分解得到的子问题数目太多,以致最后解决原问题需要耗费指数级时间。然而,不同子问题的数目常常只有多项式量级。在用分治法求解时,有些子问题被重复计算了许多次。如果能够保存已解决的子问题的答案,在需要时再找出已求得的答案,这样可以避免大量的重复计算,从而得到多项式时间算法。(所以动态规划又叫填表法

动态规划适用于解最优化问题,通常4个步骤

1.找出最优解的性质,并刻画其结构特征。

2.递归地定义最优解。

3.自底向上的方式计算最优值。

4.根据计算最优值时得到的信息构造最优解。

最优子结构:问题的最优解包含了其子问题的最优解。

重叠子问题:递归自顶向下解问题时,每次产生的子问题不总是新问题,有些子问题被反复计算。动态规划对每个子问题只解一次,然后将解保留在一个表格中。

相同的子问题反复出现,并且不同子问题的个数相对较小时,用动态规划算法是有效的。

矩阵连乘问题

求需要的数乘次数最少

 

假设A1,A2,A3矩阵维数分别是10*100,100*5,5*50,

如果按((A1A2)A3)计算,3个矩阵连乘积需要数乘次数=10*100*5+10*5*50=7500

如果按(A1(A2A3))计算,3个矩阵连乘积需要数乘次数=100*5*50+10*100*50=75000

以此类推......

将矩阵连乘积A1*A2*...*An记为A[i:j]。

所以A[1:n]的计算量就是A[1:k]的计算量加上A[k+1:An]的计算量,再加上A[1:k]和A[k+1:n]相乘的计算量。

那么A[1:n]如果是最优的,A[1:k]和A[k+1:n]这俩必须也是最优的

设A[i,j]所需的最少乘次数为m[i][j]。

其中k还未定,k的位置有j-i种可能,k是这j-i个位置中使计算量达到最小的那个位置。

但是这样的话,许多子问题被重复计算多次

所以还有记录最优断开位置的数组s和记录输入参数的数组p。

void MatrixChain(int *p, int n, int **m, int **s){
    for(int i=1;i<=n;i++)
        m[i][i]=0;    
        //填表,只有一个矩阵,都没有矩阵和它乘,数层数次数等于0
        //也就是表的对角线都填0
    for(int r=2;r<=n;r++){
        for(int i=1;i<=n;i++){
            int j=i+r-1;
            //对角线向上平移r格得新的斜线,开始走这条新斜线,这个斜线上列比行多r-1(r从2到n)
            //r最开始是2,j比i多1,总共两个矩阵相乘求连乘次数
            //当r=n已经把表填完了,两个for嵌套循环结束
            //很明显这是自底向下的

            m[i][j]=m[i+1][j]+p[i-1]*p[i]*p[j];    //m[i][j]最开始的初值
            //默认是i处断开,m[i][j]=0+m[i+1][j]+p[i-1]*p[i]*p[j]
            //左边乘次数0,右边乘次数m[i+1][j]
            //左右相乘次数p[i-1]*p[i]*p[j]
            
            s[i][j]=i;    //s[i][j]最开始的初值

            for(int k=i+1;k<j;k++){    //for循环之后,最优值t赋给m[i][j]
                int t=m[i][k]+m[k+1][j]+p[i-1]*p[k]*p[j];
                if(t<m[i][j]){
                    m[i][j]=t;
                    s[i][j]=k;    //i和j之间断开处为s[i][j](也就是k)的时候得到最优值
                }
            }
        }
    }
}

计算次序如下图,可以看出是自底向上。最开始填表解决的是简单问题,最后得到复杂问题的解。

备忘录方法

与动态规划算法不同的是,备忘录方法的递归方式是自顶向下的,而动态规划算法则是自底向上递归的。因此,备忘录方法的控制结构与直接递归方法的控制结构相同,区别在于备忘录方法为每个解过的子问题建立了备忘录以备需要时查看,避免了相同子问题的重复求解。

最长公共子序列

一个给定序列的子序列是在该序列中删除若干元素后得到的序列。

最长公共子序列具有最优子结构的性质。

递归结构/递归关系

计算最优值:最长公共子序列的长度c[m][n](X长度m,Y长度n)

void LCSLength(int m, int n, char *x, char *y ,int **c,int **b){
    int i,j;
    for(i=1;i<=m;i++)
        c[i][0]=0;    //j=0的位置都填0,因为Xi和一个空序列的公共子序列肯定空。
    for(i=1;i<=n;i++)
        c[0][i]=0;    //同理,i=0的位置都填0
    for(i=1;i<=m;i++){
        for(j=1;j<=n;j++){
            if(x[i]==y[j]){
                c[i][j]=c[i-1][j-1]+1;    
                b[i][j]=1;    //b[i][j]用来记录c[i][j]的值是由哪个子问题得到的。
                //1是Xm=Yn,则Zk=Xm=Yn,且Zk-1是Xm-1和Yn-1的最长公共子序列,也就是上上图的圈1和上图的中间那行。
            }    //下面是为了找c[i][j]的取值,也就是c[i-1][j]和c[i][j-1]中更大的那个,此时Xi和Yi的最后一个元素不相等。Xi和Yj的最长公共子序列应该和Xi-1和Yj的最长公共子序列或Xi和Yj-1的最长公共子序列相等,要求长度最长,取两者中较大的
                else if(c[i-1][j]>=c[i][j-1]){
                c[i][j]=c[i-1][j];
                b[i][j]=2;
                //2是上上图的圈2 和 上图的第三行更大的是c[i-1][j]
            }
            else{
                c[i][j]=c[i][j-1];
                b[i][j]=3;
                //3是上上图的圈3 和 上图的第三行更大的是c[i][j-1]
            }
        }
    }
}

构造最长公共子序列

//刚刚的代码只求了长度,下面的代码可以打印最长公共子序列

void LCS(int i,int j, char *x, int **b){
    if(i==0||j==0)    到头返回
        return;
    if(b[i][j]==1){
        LCS(i-1,j-1,x,b);    //x[i]和y[j]相等,输出任意一个都行
        cout<<x[i];          //相同元素的输出,最后一定会把公共子序列的元素都输出出来。
    }
    else if(b[i][j]==2)
        LCS(i-1,j,x,b);    //这种情况是Z是Xi-1和Yj的最长公共子序列 
    else
        LCS(i,j-1,x,b);    //这种情况是Z是Xi和Yj-1的最长公共子序列
}

最大字段和

没画重点,不写。

四 贪心算法

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1841390.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【机器学习300问】126、词嵌入(Word Embedding)是什么意思?

人类的文字&#xff0c;作为一种高度抽象化的符号系统&#xff0c;承载着丰富而复杂的信息。为了让电脑也能像人类一样理解并处理这些文字&#xff0c;科学家们不断探索各种方法&#xff0c;以期将人类的语言转化为计算机能够理解的格式。 一、One-Hot编码的不足 在自然语言处…

每月策略会议

周一顾问策略会议&#xff0c;对于企业辅导而言&#xff0c;领导力是可以培训的&#xff0c;而决策力不是靠培训就能达成&#xff0c;是需要反复训练和反思。从最为关心的一个状况出发&#xff0c;去行动才会有结果&#xff0c;有了结果反思我们的假设是否有盲区是否有误才有可…

LVGL开发教程-Grid(网格布局)

系列文章目录 知不足而奋进 望远山而前行 目录 系列文章目录 文章目录 前言 1. 常用方法 2. 代码实现 总结 前言 网格布局&#xff08;Grid Layout&#xff09;是一种强大的布局方式&#xff0c;它允许将项目按照行和列的二维表格方式进行排列。LVGL&#xff08;Little…

分布式之日志系统平台ELK

ELK解决了什么问题 我们开发完成后发布到线上的项目出现问题时(中小型公司),我们可能需要获取服务器中的日志文件进行定位分析问题。但在规模较大或者更加复杂的分布式场景下就显得力不从心。因此急需通过集中化的日志管理,将所有服务器上的日志进行收集汇总。所以ELK应运而生…

Android Glide, first start based on loadThumbnail, Kotlin(二)

Android Glide, first start based on loadThumbnail, Kotlin&#xff08;二&#xff09; Android Glide, first start based on loadThumbnail, Kotlin&#xff08;一&#xff09;中有个小问题&#xff0c;通过loadThumbnail()采集到的缩略图真的就是整张图片的完整缩略图&…

NET Core C# 中的Action委托:语法、用法和示例_2024-06-19

Action委托是一个内置的泛型委托类型。此委托使您的程序更具可读性和效率&#xff0c;因为您无需定义自定义委托&#xff0c;如以下示例所示。 它在 System 命名空间下定义。它没有输出参数&#xff0c;输入参数最少为 1 个&#xff0c;最多为 16 个。 Action委托通常用于具有…

高压电阻器支持牙科 X 射线成像的准确性

为了捕获患者牙齿和颌骨的足够图像&#xff0c;牙医依靠锥形束计算机断层扫描 &#xff08;CBCT&#xff09; 系统的先进 3D 成像。CBCT系统的输出对于准确诊断口腔健康问题和随后的治疗计划至关重要。为了确保这些图像的可靠性&#xff0c;CBCT系统制造商利用了Exxelia Ohmcra…

【bug】配置SpringCloudAlibaba AI的maven依赖问题

问题描述 尝鲜alibaba的ai模块&#xff0c;maven依赖一直报找不到包&#xff0c;报错如下 Unresolved dependency: org.springframework.ai:spring-ai-core:jar:0.8.1原因分析&#xff1a; 由于是按照官方文档配置的&#xff0c;所以检查了很多遍maven配置&#xff0c;加上去…

给电脑bios主板设置密码

增强安全性&#xff1a;防止未经授权的人员更改 BIOS 中的重要设置&#xff0c;如启动顺序、硬件配置等。这有助于保护计算机系统的稳定性和数据的安全性。防止恶意篡改&#xff1a;阻止可能的攻击者或恶意软件通过修改 BIOS 设置来破坏系统或获取敏感信息。数据保护&#xff1…

阿里云 debian10.3 sudo apt-get updat 报错的解决方案

阿里云全新的debian10.3(buster)镜像&#xff0c;却无法正常执行 sudo apt-get update。主要报错信息如下&#xff1a; Err:6 http://mirrors.cloud.aliyuncs.com/debian buster-backports Release404 Not Found [IP: 100.100.2.148 80] Err:3 http://mirrors.cloud.aliyuncs…

【JavaEE 进阶(五)】SpringBoot日志

❣博主主页: 33的博客❣ ▶️文章专栏分类:JavaEE◀️ &#x1f69a;我的代码仓库: 33的代码仓库&#x1f69a; &#x1faf5;&#x1faf5;&#x1faf5;关注我带你了解更多进阶知识 目录 1.前言2.日志使用2.1打印日志2.2 门面模式(外观模式)2.3SLF4J框架2.4日志格式说明 3.Sl…

MySQL----配置主从复制

环境 master(CtenOS7)&#xff1a;192.168.200.131 ----ifconfig查看->ens33->inet slave(win10)&#xff1a;192.168.250.52 ----ipconfig查看->无线局域网适配器 WLAN:-> IPv4 地址 保证两个环境中MySQL版本一致 网络互通 win&#xff1a;ping 192.168.200.13…

NL2SQL进阶系列(1):DB-GPT-Hub、SQLcoder、Text2SQL开源应用实践详解

1. MindSQL(库) MindSQL 是一个 Python RAG&#xff08;检索增强生成&#xff09;库&#xff0c;旨在仅使用几行代码来简化用户与其数据库之间的交互。 MindSQL 与 PostgreSQL、MySQL、SQLite 等知名数据库无缝集成&#xff0c;还通过扩展核心类&#xff0c;将其功能扩展到 Sn…

【五子棋】C语言教程

Hi~&#xff01;这里是奋斗的小羊&#xff0c;很荣幸您能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎 ~~ &#x1f4a5;&#x1f4a5;个人主页&#xff1a;奋斗的小羊 &#x1f4a5;&#x1f4a5;所属专栏&#xff1a;C语言 &#x1f680;本系列文章为个人学习…

webhook-k8s API和apimachinery版本高于Client-go

1. 问题 使用go mod tidy 存在丢弃的版本 go: downloading github.com/josharian/intern v1.0.0 go: finding module for package k8s.io/api/flowcontrol/v1alpha1 go: simple-webhook/types importsk8s.io/client-go/rest tested byk8s.io/client-go/rest.test importsk8s.…

大数据-数据分析初步学习,待补充

参考视频&#xff1a;数据分析只需3小时从入门到进阶&#xff08;up亲身实践&#xff09;_哔哩哔哩_bilibili 数据指标&#xff1a; 对当前业务有参考价值的统计数据 分类&#xff1a;用户数据&#xff0c;业务数据&#xff0c;行为数据 用户数据 存量&#xff1a; DAU&#…

基于Vue3.0 Node.js 的 大文件切片上传、秒传、断点续传实现方案梳理

✨&#x1f4bb; 在处理大文件上传时&#xff0c;切片上传是提高效率与用户体验的关键技术之一。下面将详细介绍如何在前端利用Vue框架与Node.js后端配合&#xff0c;实现这一功能。 &#x1f446;&#x1f3fb;大体流程 &#x1f446;&#x1f3fb;一、文件切片上传 通过文件…

43、基于神经网络拟合函数的体脂估计(matlab)

1、神经网络拟合函数的原理及流程 神经网络拟合函数是一种基于人工神经元之间相互连接的模型&#xff0c;用来拟合复杂的非线性函数关系。其原理是通过多层次的神经元网络&#xff0c;每一层神经元通过激活函数将输入信号加权求和后输出&#xff0c;经过多次迭代优化权值&…

Java 集合框架详谈及代码分析(Iterable->Collection->List、Set->各接口实现类、Map->各接口实现类)

目录 Java 集合框架详谈及代码分析&#xff08;Iterable->Collection->List、Set->各接口实现类、Map->各接口实现类&#xff09;1、集合概述1-1&#xff1a;Java 集合概述1-2&#xff1a;List、Set、Map 三者的区别&#xff1f;1-3&#xff1a;集合框架底层数据结…

python电灯开关 青少年编程电子学会python编程等级考试三级真题解析2021年12月

python电灯开关 2021年12月 python编程等级考试级编程题 一、题目要求 1、编程实现 n个灯排成一排&#xff0c;开始时都是关着的。现进行如下操作: 所有电灯的按钮按动一次;所有编号为2的倍数的电灯按钮按动一次;所有编号为3的倍数的电灯的按钮按动一次: …所有编号为n-1的…