分析和设计算法

news2024/11/20 1:36:33

目录

前言 

循环不变式

n位二进制整数相加问题

RAM模型

使用RAM模型分析

代码的最坏情况和平均情况分析

插入排序最坏情况分析

插入排序平均情况分析

设计算法

分治法

总结


前言 

        循环迭代,分析算法和设计算法作为算法中的三个重要的角色,下面从一些程序示例入手,介绍如何使用有效的方法来设计和分析算法。

循环不变式

代码:

int f(int n) {
    int res = 1;
    for(int i = 1; i <= n; i++) {
        res = res * i;
    }
    return res;
}

这是求n!的函数, res是每次迭代的(i-1)!的结果,可以看到每趟迭代下来,它的形式都是res,没有变更过,我们称之为循环不变式

循环不变式有初始化,保持和终止三要素。

初始化:循环的第一次迭代,它为真。代码中如果res = 0; 则第一次迭代的结果res = 0;

结果为假,初始化错误。

保持:如果本次迭代结果为真,则下一次的结果也为真。本次res = i!, 下一次res = res * (i+1) = i! * (i + 1) = (i+1)!. 可以理解为迭代保持了。

终止:迭代终止的条件, i > n时,迭代终止。数学归纳法中只有初始化和保持的证明,但是没有终止这一步。当i叠加到n+1时,上一次迭代结果时res = res*i = i! = n!已经是正确结果了,所以迭代条件终止时,结果正确。

n位二进制整数相加问题

初始化:A[MAXSIZE] = {0}, B[MAXSIZE] = {0}, C[MAXSIZE] = {0}.

保持:C[i+1] = (A[i] + B[i] + C[i])/2; C[i] = (A[i] + B[i] + C[i])%2.

终止条件:A[i]和B[i]中全部为零,迭代终止.

代码:

void num_to_binary(int num, int B[MAXSIZE]) {
    for (int i = 0; num > 0; i++)
    {
        B[i] = num % 2;
        num = num / 2;
        printf("%d", B[i]);
    }
    printf("\n");
    
}

void binary_add(int A[MAXSIZE], int B[MAXSIZE], int C[MAXSIZE + 1]) {
    int i;
    for (i = 0; B[i] || A[i] ; i++)
    {
        C[i+1] = (A[i] + B[i] + C[i]) / 2;
        C[i] = (A[i] + B[i] + C[i]) % 2;
        printf("%d", C[i]);
    }
    printf("%d\n", C[i]);
}

输出结果:

RAM模型

在分析算法时,我们经常提到时间复杂度和空间复杂度。这些都是基于代码中的指令是一条一条地在CPU中执行的,不存在并行操作。这种前提可以理解位RAM模型。

使用RAM模型分析

代码

代价

次数

int res = 1;

C1

1

for(int i = 1; i <= n; i++)

C2

n

res = res * i;

C3

n

return res;

C4

1

上述代码的运行时间位Tn=c1+c2*n+c3*n+c4.

T(n)为n的线性函数,所以可以说改代码的时间复杂度为O(n).

代码的最坏情况和平均情况分析

  for(int i = 0; i < 10; i++) {
        while (p->next)
        {
            lnode *q = p->next;
            if(q->data > data[i]) {
                lnode *node = (lnode *) malloc(sizeof(lnode));
                node->data = data[i];
                node->next = q;
                p->next = node;
                break;
            }
            p = p->next;
        }
        p = list;
}
}
插入排序最坏情况分析

10个元素参与插入排序,最坏情况下,每趟插入的位置都是表尾:

第一趟  比较1次

第二趟  比较2次

。。。

第n趟  比较n次

T(n) = (1+2+3+…+n) + c = (n+1)*n/2 + cn.(c为插入一个结点的时间复杂度)。

插入排序平均情况分析

平均比较次数:

第一趟 比较(1+1)/2

第二趟 比较(1+2)/2

。。。

第n趟 比较(1+n)/2

T(n) = n*n/4 + cn.

在n足够大的时候,可以认为插入排序的最坏情况和平均情况的时间复杂度均为O(n*n).

设计算法

分治法

分治三个步骤:

分解:分解原问题为子问题,这些子问题为原问题的较小规模的问题。

解决:递归地解决这些子问题,如果规模小到一定程度,则直接得出答案。

合并:合并上述解决地子问题地解,得出最终解。

前提:该集合S经过归并排序之后的序列再进行如下算法运算。

分解:集合S的n个问题分解成两个规模n/2的问题。

解决:递归的解决和分解这些子问题,直到规模为2时,两个数相加与x比较,如果相等则存在,否则返回不存在。

合并:合并两个子问题,两个子问题中不存在和等于x的情况,所以需要判断是否存在跨集合相加和等于x的情况。

代码:

#include "stdio.h"
#define OK 1
#define ERROR 0
#define MAXSIZE 10
int FLAG = 0;
int is_x(int a1[MAXSIZE], int x, int low, int mid, int high);
void jude_add_x(int a[MAXSIZE], int x, int low, int high);

void main() {
    int b[10] = {-1,2,3,5,9,27,29,38,49,74};
    int x = 8;
    jude_add_x(b, x, 0, 9);
    printf("The result is %d", FLAG);
}

int is_x(int a1[MAXSIZE], int x, int low, int mid, int high) {
    
    int i = low, j = mid+1, k = low;
    while (i <= mid || j <= high)
    {
        if(a1[i] + a1[j] == x) 
        {
            return OK;
        }else if(a1[i] + a1[j] < x) {
            if(i < mid) i++;
            else if( j <= high) j++;
            else return ERROR;
        }else {
            return ERROR;
        }
    } 
    return ERROR;
}

void jude_add_x(int a[MAXSIZE], int x, int low, int high) {

    if(low == high) {
        return;
    }
    int mid = (low + high) / 2;
    jude_add_x(a, x, low, mid);
    jude_add_x(a, x, mid + 1, high);
    if(low != high && is_x(a, x, low, mid, high)) FLAG = 1;
}

 输出结果:

时间复杂度:O(lgn*n) 

空间复杂度:   O(1)

总结

本文主要讲解如何分析和设计算法。分析算法从分析时间复杂度入手,讲述了最坏情况和平均情况下的分析。设计算法以一个程序入手,讲述了分治法的三个步骤怎么分析。

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

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

相关文章

【网络安全的神秘世界】docker搭建pikachu靶场

&#x1f31d;博客主页&#xff1a;泥菩萨 &#x1f496;专栏&#xff1a;Linux探索之旅 | 网络安全的神秘世界 | 专接本 docker搭建pikachu靶场 通过docker安装pikachu 访问docker官网查找pikachu&#xff1a; https://hub.docker.com/search?qapache 复制命令后&#xff…

SpringCloud Feign用法

1.在目标应用的启动类上添加开启远程fein调用注解&#xff1a; 2.添加一个feign调用的interface FeignClient("gulimall-coupon") public interface CouponFeignService {PostMapping("/coupon/spubounds/save")R save(RequestBody SpuBondTo spuBounds);…

自然语言处理学习路线

学习目标 NLP 系统知识&#xff08;从入门到入土&#xff09; 学习内容 NLP的基本流程&#xff1a;&#xff08;待更&#xff09;文本预处理&#xff08;标点符号处理、繁体转简体、分词Tokenizer&#xff09;&#xff1a;&#xff08;待更&#xff09;词袋模型&#xff08;TF…

VSCode Prettier - Code formatter 代码格式化

格式化代码是一个挑战&#xff0c;但现代开发工具可以自动保持团队代码库的一致性。 在本文中&#xff0c;您将设置 Prettier 以自动格式化 Visual Studio Code&#xff08;也称为 VS Code&#xff09;中的代码。 1. 安装插件 2. 定义代码风格 在项目根目录下创建一个pretti…

SpringBoot HelloWorld 之 实现注册功能

SpringBoot HelloWorld 之 实现注册功能 一.配置 创建数据库big_event CREATE TABLE user (id int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT ID,username varchar(20) COLLATE utf8_unicode_ci NOT NULL COMMENT 用户名,password varchar(32) COLLATE utf8_unicode_ci …

海外动态IP代理可以用来批量注册邮箱吗?

无论是个人还是企业&#xff0c;都需要使用邮箱进行沟通、注册账号、接收通知等多种用途。然而&#xff0c;由于互联网服务商为了防止滥用和垃圾邮件的传播&#xff0c;通常对注册邮箱设置了一定的限制&#xff0c;如IP限制、验证码验证等。为了解决这些问题&#xff0c;海外动…

儿童节快乐!探索图形化编程桌面的“童年”成长之路

在这个充满童真与快乐的儿童节&#xff0c;我要向在CSDN平台上努力拼搏的每一位朋友&#xff0c;送上我最热切、最深情的祝福&#xff01;愿你们心中那份孩童般的纯真与对世界无尽的好奇永不褪色&#xff0c;愿你们的人生道路如同这个美好的节日&#xff0c;流光溢彩、欢乐永恒…

提示工程(Prompt Engineering)和代码生成

文心一言 提示工程&#xff08;Prompt Engineering&#xff09;和代码生成之间的关系主要体现在如何通过精心设计的提示来指导或优化代码生成的过程。以下是关于提示工程和代码生成的详细解释&#xff1a; 一、提示工程&#xff08;Prompt Engineering&#xff09; 提示工程…

Centos给普通用户添加sudo命令权限

打开sudoers文件 sudo visudo 修改sudoers文件 找到root ALL(ALL) ALL这一行&#xff0c;即如下图标出红线的一行 在此行下新增如下内容: lbs为用给予sudo执行权限的用户名 # 执行sudo命令&#xff0c;需要输入命令 lbs ALL(ALL) ALL 或 # 执行sudo命令&#xff0c;…

【Python】如何使用 Python 自动发送每日电子邮件报告

人不走空 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌赋&#xff1a;斯是陋室&#xff0c;惟吾德馨 目录 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌…

数组中的第K个最大元素,力扣

目录 题目地址&#xff1a; 我们直接看题解吧&#xff1a; 快速理解解题思路小建议&#xff1a; 审题目事例提示&#xff1a; 解题方法&#xff1a; 解题分析&#xff1a; 解题思路&#xff1a; 题目地址&#xff1a; 215. 数组中的第K个最大元素 - 力扣&#xff08;LeetCode&a…

如何在 llama.cpp 服务器中实现用户登录功能的优化方案?(语言-c++)

&#x1f3c6;本文收录于「Bug调优」专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收藏&&…

寺庙小程序-H5网页开发

大家好&#xff0c;我是程序员小孟。 现在有很多的产品或者工具都开始信息话了&#xff0c;寺庙或者佛教也需要小程序吗&#xff1f; 当然了&#xff01; 前面我们还开发了很多寺庙相关的小程序。 今天要介绍的是一款寺庙系统&#xff0c;该系统可以作为小程序、H5网页、安…

自用了很久的一款强制卸载软件,超级好用!!!

Ashampoo UnInstaller是一款由Ashampoo公司开发的专业卸载工具&#xff0c;它提供了比Windows自带卸载功能更为彻底的程序卸载解决方案。是一款功能强大的卸载工具&#xff0c;旨在帮助用户彻底删除不需要的程序和应用&#xff0c;卸载难以卸载的软件工具&#xff0c;此外他还有…

【SQL学习进阶】从入门到高级应用(九)

文章目录 子查询什么是子查询where后面使用子查询from后面使用子查询select后面使用子查询exists、not existsin和exists区别 union&union alllimit &#x1f308;你好呀&#xff01;我是 山顶风景独好 &#x1f495;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面…

Python代码优化工具memory_profiler

1. 工具介绍 memory_profiler是Python的一个第三方库&#xff0c;其功能时基于函数的逐行代码分析工具。通过该库&#xff0c;可以对目标函数(允许分析多个函数)进行内存消耗分析&#xff0c;便于代码调优。 2. 安装 pip install memory_profiler 3. 使用 from memory_pro…

[香橙派 AIpro] 性能强劲的昇腾AI开发板,应用广泛,性能出众,遥遥领先!

[香橙派 AIpro] 性能强劲的昇腾AI开发板&#xff0c;应用广泛&#xff0c;性能出众&#xff0c;遥遥领先&#xff01; 开发板简介 香橙派AIpro开发板凭借华为昇腾AI芯片的强大算力、丰富的接口、完善的开发工具等优势&#xff0c;在AI开发板市场具有很高的竞争力&#xff0c;可…

wpf listbox实现选中动画

效果如下&#xff1a; 参考&#xff1a;https://github.com/WPFDevelopersOrg/WPFDevelopers/blob/master/src/WPFDevelopers.Samples.Shared/Controls/NavigateMenu/NavigateMenu.xaml 实现上述效果的前台代码&#xff1a; <Windowx:Class"ListBox.MainWindow"…

Blender 学习笔记(二)游标与原点

1. 游标 游标是界面中的红色圆圈&#xff1a; 1.1 移动游标 我们可以通过点击工具栏中的游标按钮&#xff0c;来移动游标&#xff0c;或者通过快捷键 shift右键 移动。若想要重置复游标位置&#xff0c;可以用 shiftc 恢复&#xff0c;或则通过 shifts 点击 游标->世界原…

Linux系统编程——动静态库

目录 一&#xff0c;关于动静态库 1.1 什么是库&#xff1f; 1.2 认识动静态库 1.3 动静态库特征 二&#xff0c;静态库 2.1 制作静态库 2.2 使用静态库 三&#xff0c;动态库 3.1 制作动态库 3.2 使用动态库一些问题 3.3 正确使用动态库三种方法 3.3.1 方法一&…