IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 2021-09-10 -> 正文阅读

[数据结构与算法]2021-09-10

算法分析

第一次

程序设计一般步骤
1 确定数据结构
2 确定算法
3 编写程序
4 调试程序
5 编写文档资料

上述5个步骤中最重要的第2步 确定算法
算法:所谓算法是指某个问题或者某个功能的求解方法。

实际中某个问题或者某个功能的求解方法不止一个。

考虑选择哪种算法作为我该问题或者该功能的最终解决方案呢?

1 算法正确

2 时间复杂度和空间复杂度

例1 输入一个正整数给x,判断其是否是素数?

分析 所谓素数就是质数:也就是只能被1和其本身(x)整除的数
其实任何额一个正整数都能被1和其本身整除,而这点其实可以不证明
重点去证明:不能被2到x-1范围内的所有的数整除。
举例:
x=7 2 3 4 5 6
2到6中每个数值都与7之间是不能整除的关系,所以7才是素数

x=8 2 3 4 5 6 7
8对2取余数就是0,整除关系,结果可以直接下结论8不是3到7就没必要再进行判断了,循环可以提前结束。

整个问题中涉及2个问题,是素数1,不是素数0
代码1
#include"stdio.h"
#include"windows.h"
int main()
{
int x,i,flag;//flag=1 是素数 flag=0 表示不是素数

printf(“请你任意输入一个正整数:”);
scanf("%d",&x);

flag=1;//相当于一开始假设x是素数
for(i=2;i<=x-1;i++)
{
if(x%i==0)
{
flag=0;
break;
}
}

if(flag==1)
printf(“yes”);
else
printf(“no”);
system(“pause”);
}

上述程序的时间复杂度是多少? o(n)


时间复杂度的表示形式是 o(?)

1 白话解释:看程序运行所耗费的时间

2 专业理解:形式o(?)

?体现出来的就是一个问题求解过程中操作的执行次数。
执行次数要把问题放大到n个数值的角度来看待。

特别注意: 专业理解时间复杂度的问题,把一个问题求解方法的过程,放大到n个数值类似的角度来看待问题。
举例说明:s=1+2+3+4+…+100

方法1 用等差数列求和公式来表示
s=(1+100)*100/2;
时间复杂度 o(1)
注意这里1 表示操作的执行次数

方法2 用循环
s=0;
for(i=1;i<=100;i++)
s=s+i;
时间复杂度 o(n)
注意这里n 表示操作的执行次数


如果在之前所学过的输出所有三位数值中的水仙花数。

for(a=1;a<=9;a++)
for(b=0;c<=9;b++)
for(c=0;c<=9;c++)
{
t=a100+b10+c;
if(t==aaa+bbb+ccc)
printf("%d\n",t);
}

白话解释 91010

时间复杂度 o(nnn) 等价 o(n^3)


改进素数程序

举例

x=7 2 3 4 5 6 2到6中每个数值都与7之间是不能整除的关系,所以7才是素数

x=8 2 3 4 5 6 7 8对2取余数就是0,整除关系,结果可以直接下结论8不是
3到7就没必要再进行判断了。
循环可以提前结束。

注意 上述方法中
其实对于7而言 4 5 6没必要判断,因为它们都超过了7的一半,所以不可能是整除关系
其实对于8而言 5 6 7没必要判断,因为它们都超过了8的一半,所以不可能是整除关系

最后修改的是循环 for(i=2;i<=x/2;i++)

代码2
#include"stdio.h"
#include"windows.h"
int main()
{
int x,i,flag;//flag=1 是素数 flag=0 表示不是素数

printf(“请你任意输入一个正整数:”);
scanf("%d",&x);

flag=1;//相当于一开始假设x是素数
for(i=2;i<=x/2;i++)
{
if(x%i==0)
{
flag=0;
break;
}
}

if(flag==1)
printf(“yes”);
else
printf(“no”);
system(“pause”);
}
白话理解:运算次数少了
专业理解:时间复杂度是多少呢? o(n)


继续修改

4不是素数 因为2
6不是素数 因为2
8不是素数 因为2
9不是素数 因为3
10不是素数 因为2
12不是素数 因为2
14不是素数 因为2
15不是素数 因为3
16不是素数 因为2
。。。。。。。。。。。
25不是素数 因为5
26不是素数 因为2

所以每个数值x是否是素数,判断范围还可以缩小,2到x的平方根 sqrt(x)

代码2
#include"stdio.h"
#include"windows.h"
#include"math.h"
int main()
{
int x,i,flag;//flag=1 是素数 flag=0 表示不是素数

printf(“请你任意输入一个正整数:”);
scanf("%d",&x);

flag=1;//相当于一开始假设x是素数
for(i=2;i<=sqrt(x);i++)
{
if(x%i==0)
{
flag=0;
break;
}
}

if(flag==1)
printf(“yes”);
else
printf(“no”);
system(“pause”);
return 0;
}

白话理解:运算次数少了
专业理解:时间复杂度是多少呢? o(logn)


最后提醒一下

一般我们强调某个方法的时间复杂度,应该是包含该问题求解方法的所有步骤所耗费的时间

实际处理的是一个问题求解方法中,所有步骤中取耗费时间(次数)最多的作为最后的时间复杂度的描述

一般情况下,时间复杂度的表示形式如下常见的5种

1 o(1)
2 o(n)
3 o(logn)
4 o(n*logn)
5 o(n^3) 或者 o(n^?)


例2 1-1000这1000个数放在含有1001个元素的数组中,只有唯一的一个元素值重复,
其他均只出现一次。设计一个算法,将它找出来,你能否设计一个算法实现?

最后要找出哪个数是重复的?如果可以的话再找出具体是哪2个位置的数?

方法1 简单粗暴,我想用枚举法,暴力破解法。好处,理解简单啊

a[1]???? a[2] ????a[3] ????a[4]???? a[5]???? a[6] ????a[7]???? a[8]???? a[9] ????a[10]???? a[11]
2 ????????9???????? 8 ????????6???????? 5 ????????4???????? 1???????? 3 ????????7 ????????10???????? 8
最终考虑到是任意输入的情况

(1)将a[1]与 a[2]到a[11]依次比较,如果相等则输出a[1],1,另外一个相同值的位置
for(i=2;i<=11;i++)
{
if(a[1]==a[i])
printf("%d %d %d\n",a[1],1,i);
}
(2)将a[2]与 a[3]到a[11]依次比较,如果相等则输出a[2],2,另外一个相同值的位置
for(i=3;i<=11;i++)
{
if(a[2]==a[i])
printf("%d %d %d\n",a[2],2,i);
}

(10)将a[10]与 a[11]到a[11]依次比较,如果相等则输出a[10],10,另外一个相同值的位置
for(i=11;i<=11;i++)
{
if(a[10]==a[i])
printf("%d %d %d\n",a[10],10,i);
}

上述过程再凑循环
for(j=1;j<=10;j++)
{
for(i=j+1;i<=11;i++)
{
if(a[j]==a[i])
printf("%d %d %d\n",a[j],j,i);
}
}

最后代码

#include"stdio.h"
#include"windows.h"
int main()
{
int a[12],i,j;

printf(“请你输入11个数值,且在1-10之间,且只能有一个数值重复\n”);
for(i=1;i<=11;i++)
scanf("%d",&a[i]);

for(j=1;j<=10;j++)
{
for(i=j+1;i<=11;i++)
{
if(a[j]==a[i])
printf("%d %d %d\n",a[j],j,i);
}
}

system(“pause”);
}

这里是算次数
10+9+…+1
n-1+n-2+…+1
(n-1+1)(n-1)/2
n
(n-1)/2

n^2-n/2

标准 o(1+n+(n^2-n)/2)

这里1 是定义代码的
这里n 是输入代码的
这里(n^2-n)/2 是求解代码的

最后取最大值 o(n^2)


最后的修改思路
a[1]???? a[2] ????a[3] ????a[4]???? a[5]???? a[6] ????a[7]???? a[8]???? a[9] ????a[10]???? a[11]
2 ????????9???????? 8 ????????6???????? 5 ????????4???????? 1???????? 3 ????????7 ????????10???????? 8
准备2个数组,一个数组长度11,另外一个数组长度10
数组a的每个数组元素的值,作为数组b数组元素的标号
数组b中所有数组元素初始值为0
b[1]???? b[2] ???? b[3] ???? b[4]???? b[5] ???? b[6] ???? b[7] ???? b[8] ???? b[9]???? b[10]
1???????? 1 ?????????1?????????? 1???????? 1???????? 1 ???????? 1 ???????? 2???????? 1 ???????? 1
??????????说明2出现了1次 ???????????????????????????????????????????????????????? 说明8出现了2次

#include"stdio.h"
#include"windows.h"
int main()
{
int a[12],b[12]={0},i,j,t;

printf(“请你输入11个数值,且在1-10之间,且只能有一个数值重复\n”);
for(i=1;i<=11;i++)
scanf("%d",&a[i]);

for(i=1;i<=11;i++)
{
b[a[i]]++;
if(b[a[i]]==2)
{
t=a[i];
break;
}
}

//如果输出既要位置也要输出的值,我得再来 一轮循环
for(i=1;i<=11;i++)
{
if(t==a[i])
printf(“相同值%d 相同位置%d\n”,t,i);
}
system(“pause”);
}

其实这个方法是用来 空间换时间。

最后问题该方法的时间复杂度是多少呢? o(n)

过程
1 定义部分 1
2 输入部分 n
3 求解部分 n
4 输出部分 n
最后取最大值 n


提出方法3 思路 请思考用异或(位运算)

异或 一样为0,不一样为1

如果是9

9^0 结果是 9

9^9 结果是 0

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-09-11 19:04:09  更:2021-09-11 19:05:00 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 3:42:46-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码