数据结构作业1 讲解和拓展

原题来自雪梨教育

http://www.edu2act.net/task/list/checked/

题后给出讲解和扩展

任务1_1 比较下列算法的时间复杂度

任务描述:

    下面给出4个算法,请分析下列各算法的时间复杂度,请写清楚题号,并将每个小题的分析过程写出来,并给出分析结果。

(1)

for(i = 1; i <= n; i++)scanf("%d", &num[i]);
ans = num[1]; 
for(i = 1; i <= n; i++)
{for(j = i; j <= n; j++) {s = 0;for(k = i; k <= j; k++)s += num[k];if(s > ans)ans = s;}
}

(2)

for(i = 1; i <= n; i++)scanf("%d", &num[i]);
sum[0] = 0;
for(i = 1; i <= n; i++) {sum[i] = num[i] + sum[i - 1];
}ans = num[1]; 
for(i = 1; i <= n; i++) {for(j = i; j <= n; j++) {s = sum[j] - sum[i - 1];if(s > ans) ans = s;}
}

(3)

int solve(int left, int right)
{if(left == right)return num[left];mid = (left + right) / 2;lans = solve(left, mid);rans = solve(mid + 1, right);sum = 0, lmax = num[mid], rmax = num[mid + 1];for(i = mid; i >= left; i--) {sum += num[i];if(sum > lmax) lmax = sum;}sum = 0;for(i = mid + 1; i <= right; i++) {sum += num[i];if(sum > rmax) rmax = sum;}ans = lmax + rmax;if(lans > ans) ans = lans;if(rans > ans) ans = rans;return ans;
}int main(void)
{scanf("%d", &n);for(i = 1; i <= n; i++)scanf("%d", &num[i]);printf("%d\n", solve(1, n));return 0;
}

(4)

for(i = 1; i <= n; i++)scanf("%d", &num[i]);num[0] = 0;
ans = num[1];
for(i = 1; i <= n; i++) 
{if(num[i - 1] > 0) num[i] += num[i - 1];elsenum[i] += 0;if(num[i] > ans) ans = num[i];
}

任务1_2 数字反转的时空复杂度

任务描述:

下面两个函数fun1和fun2都是实现对整数的逆序输出功能,请根据下面题目要求,给出答案。

(1) 请分析函数fun1的时间复杂度和空间复杂度;

(2) 请分析函数fun2的时间复杂度和空间复杂度。

代码如下:

 

int fun1(int n) 
{int rev = 0;while (n != 0) {int pop = n % 10;n /= 10;rev = rev * 10 + pop;}return rev;
}void fun2(int n)
{printf("%d", n % 10);if(n / 10 != 0)fun2(n / 10); 
}int main(void)
{printf("%d\n", fun1(10203)); fun2(10203);return 0;
}

 

讲解:

说频度,或者求和公式往上堆出来的解释, 都是耍流氓

没有专业名词的讲解才是讲解

 

直接粘贴我交的作业

 

先用数学说明,后解释题意并分析。

分别为O(N^3),O(N^2),O(N*logN),O(N).

数学:

1)第一个循环O(N)

对于每一个i来说,j执行n-i+1次,对于每个j来说,k执行j-i+1次,我们把常数去掉,

对于每一个i,执行的常数操作为1+2+3+...+(n-i+1),等差数列[1+(n-i+1)](n-i+1)/2约等于(n-i)^2而i=1,2,....n,分别执行常熟操作次数为(n-1)^2,(n-2)^2......1^2,0^2.,可以看出是平方函数求和,而对x^2求和n项的公式为(n^3)/3+(n^2)/2+n/6,我们只看最大,去掉常数,也就是O(N^3).

O(N^3)+O(N)当然还是O(N^3)

2)前两个循环都是O(N),下面两重循环,对于每个i,j执行n-i次,当i=1,2....n,j执行次数为n-1,n-2....1,0,可以看出是等差数列求和,最高项是(n^2)/2,去掉系数,时间复杂度为O(N^2).

加起来:O(N^2)+O(N)+O(N)=O(N^2)

3)分析solve函数:采用二分,将序列分成两份,直到不可再分,执行的两个循环加起来就是遍历一遍左右端点之间数的复杂度。我们看所有从长度为1的子数组,数量为n,合并后,所有长度为2的子数组,数量为n/2,再合并,长度为4的子数组,数量为n/4,我们会发现对于每个长度1,2^2,2^4,2^3,的子数组,遍历一遍所有长度一样的子数组的复杂度都是O(N),设一共有x种长度,2^x=n,很明显x=log(2,n)。

每次O(N),次数o(log(2,n)),乘起来O(n*logn)

看main函数,接收数据是O(N),加solve,等于O(n*logn)

4)接收数据O(N),一个循环O(N),加起来O(N)。

 

下面我根据完成的功能和思路分析一下:(思路简单,文字略长,不太会叙述)

这四个代码完成的功能都是求最大子数组(注意用词准确,子数组连续,子序列可以不连续)。

1)分别枚举每一个子数组的起点和终点,也就是i和j,对于每一个起点和终点,对中间部分求和,也就是k循环。显然有n个起点n个终点(去重减半,不影响复杂度),所以子数组数量为O(N^2),对于每个子数组,我们要遍历一下求和,子数组长度1-n不等,遍历一遍平均O(N),乘起来O(N^3).(注意可能产生时间更大的错觉)。找出所有子数组中最大的即可。

2)预处理出每一个以第一个元素开始,第i个元素结尾的子数组和,还是枚举每个起点终点,但是我们求和时直接减就可以了,不用遍历。对于每个子数组,操作为O(1),子数组数量O(N^2),所以总时间O(N^2).

3)二分,求左右两边最大子数组,取最大。但是还有一种情况:包含断点的那些子数组也要考虑,请思考那两个那两个循环为什么那么写?最后逻辑为何正确?

4)动态规划入门思想

没有枚举,num[i]的含义是以下标i结尾的所有子数组中最大的。

遍历数组,对于第i个元素,它的所有子数组下标范围有[1,i],[2,i].....[i-1,i],还有它自己,我们看i-1个元素,他的子数组为[1,i-1],[2,i-1].....[i-1]。请想num[i]的含义,我们求i结尾的,只要把i-1结尾的最大加上i就好了,当然如果i-1结尾最大子数组是负的,i结尾最大子数组就是它本身。

为什么O(N)?时间省在哪里了?我们省掉了许多没必要的计算,计算i时,之前的数组和已经都计算过,朴素算法并没有记录下来,而是重复计算,造成时间浪费。算法优化的过程就是去掉重复计算的过程。

 

1-2

fun1:时间O(log10,N),空间O(1)

FUN2:时间O(log10,N),空间O(log10,N)

第一个函数只是有限几个变量,所以空间O(1),一个循环n每次缩小十倍,时间O(log10,N).

第二个函数递归调用,这个函数没执行完就跳到另外的函数,会压函数栈,空间O(log(10,n)),

而时间还是O(log10,N),复杂度没变但是时间稍长。

 

 

 

作业完了

 

我们说拓展:如何求二维数组的最大和子数组?

如果大家看懂了之前的讲解,我给个提示:利用第二个代码和第四个代码思想的结合

 

 

解释:

1   2  3   4

-1 -2  1   2

1   3   -2  1

-1  -2  -1  -3

如图是前三行整体最大

怎么做呢?

先用第二个代码的思想,我们进行预处理

每个数代表这一列到这个数位置截止,累加和。

1  2  3  4

0  0  4  6

1  3  2  7

0  1  1  4

然后,我们枚举每一列的起点和终点分别为第0,1,2,3行

然后压缩成一维来做

比如求1-3行的这个矩形,我们拿0和3行减一下就行了

0-1,1-2,1-3,4-4=-1,-1,-2,0就是1-3行压缩后的结果

然后按一维do来做就好

时间复杂度:n行m列:

预处理:每个元素弄一遍,O(N*M)

枚举压缩:起点n个终点n个,数量:O(N^2),对于每个矩阵,我们压缩为一维,只要减一下就好,O(M)

dp:每个一维O(M)

 

求最大子长方体或者多维也一样,预处理,三维压二维,二维压一维,按一维dp来做。

 

算法优化的过程就是去除重复计算过程的过程

想象一下没有预处理没有dp的朴素做法时间是多少?

算法的魅力

 

以前写过这个问题的总结了,所以这次可能写的有点简单。看不懂再去之前博客找找

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

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

相关文章

KMP+DP1

Description 求一个字符串的所有前缀在串中出现的次数之和 Input 多组用例&#xff0c;每组用例占一行为一个长度不超过100000的字符串&#xff0c;以文件尾结束输入 Output 对于每组用例&#xff0c;输出该字符串的所有前缀在串中出现的次数之和&#xff0c;结果模256 Samp…

数据结构课上笔记5

介绍了链表和基本操作 用一组物理位置任意的存储单元来存放线性表的数据元素。 这组存储单元既可以是连续的&#xff0c;也可以是不连续的&#xff0c;甚至是零散分布在内存中的任意位置上的。因此&#xff0c;链表中元素的逻辑次序和 物理次序不一定相同。 定义&#xff1a; …

并查集入门三连:HDU1213 POJ1611 POJ2236

HDU1213 http://acm.hdu.edu.cn/showproblem.php?pid1213 问题描述 今天是伊格纳修斯的生日。他邀请了很多朋友。现在是晚餐时间。伊格纳修斯想知道他至少需要多少桌子。你必须注意到并非所有的朋友都互相认识&#xff0c;而且所有的朋友都不想和陌生人呆在一起。 这个问题…

Java设计模式(2 / 23):观察者模式

定义 观察者&#xff08;Observer&#xff09;模式定义了对象之间的一对多依赖&#xff0c;这样一来&#xff0c;当一个对象改变状态时&#xff0c;它的所有依赖者都会收到通知并自动更新。 OO设计原则&#xff1a;为了交互对象之间的松耦合设计而努力。 案例&#xff1a;气…

二叉树概述

各种实现和应用以后放链接 一、二叉树的基本概念 二叉树&#xff1a;二叉树是每个节点最多有两个子树的树结构。 根节点&#xff1a;一棵树最上面的节点称为根节点。 父节点、子节点&#xff1a;如果一个节点下面连接多个节点&#xff0c;那么该节点称为父节点&#xff0c;它…

Java设计模式(1 / 23):策略模式

定义 策略&#xff08;Strategy&#xff09;模式定义了算法族&#xff0c;分别封装起来&#xff0c;让它们之间可以互相替换 &#xff0c;此模式让算法的变化独立于使用算法的客户。 案例&#xff1a;模拟鸭子应用 一开始 新需求&#xff1a;模拟程序需要会飞的鸭子 在父类新…

Java设计模式(3 / 23):装饰者模式

文章目录定义案例1&#xff1a;三点几啦首次尝试再次尝试设计原则&#xff1a;类应该对扩展开放&#xff0c;对修改关闭尝用装饰者模式装饰者模式特征本例的类图放码过来饮料类HouseBlendDarkRoastEspressoDecaf调料装饰类MilkMochaSoyWhip运行测试类案例2&#xff1a;编写自己…

c语言知识体系

原文&#xff1a;https://blog.csdn.net/lf_2016/article/details/80126296#comments

《游戏编程入门 4th》笔记(1 / 14):Windows初步

文章目录Windows编程概述获取Windows理解Windows消息机制多任务多线程事件处理DirectX快速概览Direct3D是什么Window程序基础创建第一个Win32项目理解WinMainWinMain函数调用完整的WinMainGetMessage函数调用寻求帮助Windows编程概述 DirectX&#xff0c;流行的游戏编程库。它…

17校招真题题集(1)1-5

注&#xff1a;本系列题目全是按照通过率降序来排列的&#xff0c;基本保证题目难度递增。 1、 题目名称&#xff1a;游戏任务标记 来源&#xff1a;腾讯 题目描述 游戏里面有很多各式各样的任务&#xff0c;其中有一种任务玩家只能做一次&#xff0c;这类任务一共有1024个…

《游戏编程入门 4th》笔记(2 / 14):监听Windows消息

文章目录编写一个Windows程序理解InitInstanceInitInstance函数调用InitInstance的结构理解MyRegisterClassMyRegisterClass函数调用MyRegisterClass的作用揭露WinProc的秘密WinProc函数调用WinProc的大秘密什么是游戏循环The Old WinMain对持续性的需要实时终止器WinMain和循环…

17校招真题题集(2)6-10

注&#xff1a;本系列题目全是按照通过率降序来排列的&#xff0c;基本保证题目难度递增。 6、 题目名称&#xff1a;Fibonacci数列 来源&#xff1a;网易 题目描述 Fibonacci数列是这样定义的&#xff1a; F[0] 0 F[1] 1 for each i ≥ 2: F[i] F[i-1] F[i-2] 因此&am…

QT5的数据库

#include <QtSql> QT sql QSqlDatabase类实现了数据库连接的操作 QSqlQuery类执行SQL语句 QSqlRecord类封装数据库所有记录 QSqlDatabase类 [cpp] view plaincopy print?QSqlDatabase db QSqlDatabase::addDatabase("QOCI"); db.setHostName("localh…

数据结构课上笔记6

本节课介绍了单链表的操作实现细节&#xff0c;介绍了静态链表。 链表带头的作用&#xff1a;对链表进行操作时&#xff0c;可以对空表、非空表的情况以及 对首元结点进行统一处理&#xff0c;编程更方便。 下面给出带头的单链表实现思路&#xff1a; 按下标查找&#xff1a; …

《Unity2018入门与实战》笔记(9 / 9):个人总结

个人总结 脚本语言学习的窍门 尽可能多读、多写、多说脚本语言&#xff01; Link 游戏制作步骤 设计游戏时一般会遵循5个步骤&#xff1a; 罗列出画面上所有的对象。确定游戏对象运行需要哪些控制器脚本。确定自动生成游戏对象需要哪些生成器脚本。准备好用于更新UI的调度…

17校招真题题集(3)11-15

注&#xff1a;本系列题目全是按照通过率降序来排列的&#xff0c;基本保证题目难度递增。 11、 题目名称&#xff1a;买苹果 来源&#xff1a;网易 题目描述 小易去附近的商店买苹果&#xff0c;奸诈的商贩使用了捆绑交易&#xff0c;只提供6个每袋和8个每袋的包装(包装不…

Qt学习:QDomDocument

QDomDocument类代表了一个XML文件 QDomDocument类代表整个的XML文件。概念上讲&#xff1a;它是文档树的根节点&#xff0c;并提供了文档数据的基本访问方法。由于元素、文本节点、注释、指令执行等等不可能脱离一个文档的上下文&#xff0c;所以文档类也包含了需要用来创建这些…

《事实:用数据思考,避免情绪化决策》笔记

文章目录一分为二负面思维直线思维恐惧本能规模错觉以偏概全命中注定单一视角归咎他人情急生乱一分为二 要做到实事求是&#xff0c; 就要做到当你听到一分为二的说法时&#xff0c; 你就能迅速认识到这种说法描述的是一种两极分化的图画&#xff0c; 而两极之间存在一道巨大的…

顺序存储线性表实现

在计算机中用一组地址连续的存储单元依次存储线性表的各个数据元素,称作线性表的顺序存储结构。 顺序存储结构的主要优点是节省存储空间&#xff0c;因为分配给数据的存储单元全用存放结点的数据&#xff08;不考虑c/c语言中数组需指定大小的情况&#xff09;&#xff0c;结点之…

QT5生成.exe文件时,出现缺少QT5core.dll文件解决方法

在 http://qt-project.org/downloads 下载Qt SDK安装需要Qt版本。在QtCreator下&#xff0c;程序可以正常运行&#xff0c;但是当关闭QtCreator后&#xff0c;在DeBug目录下再运行相应的*.exe程序时&#xff0c;会提示缺少Qt5Core.dll错误。解决方法&#xff1a;添加电脑环境变…