算法
(1)计算机求解问题基本步骤:分析问题->建模->算法设计->编程实现->算法分析
(2)算法特性:确定性、有限性、可行性、输入、输出
(3)算法评价标准(设计要求):正确性高、可读性好、鲁棒性高、高效率低存储
(4)算法设计与分析基本任务:研究设计算法的一般规律和方法,算法质量判定准则
(5)函数阶的表示与证明:O、Ω、θ
第一章 绪论
第一部分:作业
1.计算复杂度
对以下各组f(n)和g(n),证明f(n)=Ο(g(n)),还是f(n)=Ω(g(n)),还是f(n)=Θ(g(n))
- f(n)=log2n2,g(n)=log2(n+5)
- f(n)=log2n2,g(n)=n1/2
- f(n)=n2,g(n)=n3
- f(n)=2n,g(n)=3n
- f(n)=2n,g(n)=100n2
2.整数拆分递归
用递归算法实现:求将正整数n无序拆分成最大数为k(称为n的k拆分)的拆分方案个数,要求所有的拆分方案不重复。
例如n=5,k=5,拆分方案有7种:
-
① 5=5
-
② 5=4+1
-
③ 5=3+2
-
④ 5=3+1+1
-
⑤ 5=2+2+1
-
⑥ 5=2+1+1+1
-
⑦ 5=1+1+1+1+1
#include<bits/stdc++.h>
using namespace std;
const int maxn = 10010;
//动态规划思想的递归
//dp(n,x)为整数n使用不大于x的整数进行拆分的所有情况总数
int dp[maxn][maxn];
int split(int n, int x)
{
//避免重复计算
if(dp[n][x] != 0) return dp[n][x];
//已经拆分到最低层
if(x == 1)
{
dp[n][x] = 1;
return dp[n][x];
}
//拆分过程出现最大数已经大于n的情况,化为两者相等情况
else if(n < x)
{
dp[n][x] = split(n, n);
return dp[n][x];
}
//拆分过程出现两者相等情况
else if(n == x)
{
dp[n][x] = split(n, x - 1) + 1;
return dp[n][x];
}
//n > x情况下,dp[n][x]可以拆分为两种情况
//1.使用了x,即dp[n-x][x]
//2.没有使用x,即dp[n][x-1]
else if(n > x)
{
dp[n][x] = split(n, x - 1) + split(n - x, x);
return dp[n][x];
}
}
int main()
{
int n, x;
cin >> n >> x;
cout << split(n, x);
}
测试结果:
第二部分:算法积累
1.哥德巴赫猜想
任一大于2的偶数,都可以表示成两个素数之和(1~2000)
- 用flag[2010]存素数判断,防止多次判断
- k <= i / 2防止分解重复
#include<bits/stdc++.h>
using namespace std;
bool flag[2010];
bool fl = true;
//试除法求素数有哪些
int isPrime(int n)
{
if(n <= 1) return 0;
if(n == 2) return 1;
for(int i = 2; i <= sqrt(n); i ++ )
if(n % i == 0) return 0;
return 1;
}
//判断哥特巴赫猜想在前2000是否成立
void solve()
{
for(int i = 4; i <= 2000; i = i + 2)
{
bool b = false;
for(int k = 2;k <= i / 2; k ++ )
{
if(flag[k] && flag[i - k])
{
b = true;
break;
}
}
if(!b) fl = false;
}
if(fl) cout << "成立" << endl;
else cout << "不成立" << endl;
}
int main()
{
ios_base::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
for(int i = 1; i <= 1998; i ++ )
flag[i] = isPrime(i);
solve();
}
2.多个1和-1之和
求解-1,1,-1,1,-1,1… (-1)n之和
#include<bits/stdc++.h>
using namespace std;
int main()
{
ios_base::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
int n;
cin >> n;
int sum;
if(n % 2 == 0) sum = 0;
else sum = -1;
cout << sum << endl;
}
3.链表寻值
以下算法用于在带头结点的单链表H中查找第一个值为x的结点,找到后返回其逻辑序号(从1计起) ,否则返回0
- 注意算法设计的鲁棒性
int findx(LinkList H, int x)
{
Node *p = H->next;
int i = 1;
while(p!=NULL && p->data != x)
{
i ++ ;
p = p->next;
}
if(p == NULL) return 0;
else return 1;
}