1.1第1 章─概论

1.1.1练习题

1.下列关于算法的说法中正确的有()。

Ⅰ.求解某一类问题的算法是唯一的

Ⅱ.算法必须在有限步操作之后停止

Ⅲ.算法的每一步操作必须是明确的,不能有歧义或含义模糊

Ⅳ.算法执行后一定产生确定的结果

A. 1 个B.2 个C.3 个D.4 个

2. T(n)表示当输入规模为n时的算法效率,以下算法效率最优的是()。

A.T(n)= T(n-1)+1,T(1)=1 C.T(n)= T(n/2)+1,T(1)=1

B.T(n)= 2n

D.T(n)=3nlog2n

3.什么是算法?算法有哪些特征?

4.判断一个大于2的正整数n是否为素数的方法有多种,给出两种算法,说明其中一种算法更好的理由。

5.证明以下关系成立:

(1)10n-2n=(n)

(2)2=(2)

6.证明O(f(n))+O(g(n))=O(max{f(n),g(n)})。

7.有一个含n(n>2)个整数的数组a,判断其中是否存在出现次数超过所有元素一半的元素。

8.一个字符串采用string 对象存储,设计一个算法判断该字符串是否为回文。

9.有一个整数序列,设计一个算法判断其中是否存在两个元素和恰好等于给定的整数k。

10.有两个整数序列,每个整数序列中所有元素均不相同。设计一个算法求它们的公共元素,要求不使用STL 的集合算法。

11.正整数n(n>1)可以写成质数的乘积形式,称为整数的质因数分解。例如,12=2*2*3,18=2*3*3,11=11。设计一个算法求n这样分解后各个质因数出现的次数,采用vector 向量存放结果。

12.有一个整数序列,所有元素均不相同,设计一个算法求相差最小的元素对的个数。如序列4、1、2、3的相差最小的元素对的个数是3,其元素对是(1,2),(2,3),(3,4)。

13.有一个map<string,int>容器,其中已经存放了较多元素。设计一个算法求出其中重复的value 并且返回重复value 的个数。

14.重新做第10题,采用map 容器存放最终结果。

15.假设有一个含n(n>1)个元素的stack<int>栈容器st,设计一个算法出栈从栈顶到栈底的第k(1≤k≤n)个元素,其他栈元素不变。

算法设计

1.1.2练习题参考答案

1.答:由于算法具有有穷性、确定性和输出性,因而Ⅱ、Ⅲ、Ⅳ正确,而解决某一类问题的算法不一定是唯一的。答案为C。

2.答:选项A的时间复杂度为O(n)。选项B的时间复杂度为O(n)。选项C的时间复杂度为O(log2n)。选项D 的时间复杂度为O(nlog2n)。答案为C。

3.答:算法是求解问题的一系列计算步骤。算法具有有限性、确定性、可行性、输入性和输出性5 个重要特征。

4.答:两种算法如下:

#include <stdio.h>

#include <math.h>

boolisPrime1(intn)//方法1

{for (int i=2;i<n;i++)

if (n%i==0)

return false;

return true;

}

boolisPrime2(intn)//方法2

{for (int i=2;i<=(int)sqrt(n);i++)

if (n%i==0)

return false;

return true;

}

voidmain()

{int n=5;

printf("%d,%d\n",isPrime1(n),isPrime2(n));

}

方法1 的时间复杂度为O(n),方法2的时间复杂度为n,所以方法2 更好。5.答:(1)当n 足够大时,(10n-2n)/( n)=10,所以10n-2n=(n)。

(2)2=2*2=(2)。

6.证明:对于任意f1(n)∈O(f(n)),存在正常数c1 和正常数n1,使得对所有n≥n1,有f1(n)≤c1f(n)。

类似地,对于任意g1(n)∈O(g(n)),存在正常数c2 和自然数n2,使得对所有n≥n2,有g1(n)≤c2g(n)。

令c3=max{c1,c2},n3=max{n1,n2},h(n)= max{f(n),g(n)}。

则对所有的n≥n3,有:

f1(n) +g1(n)≤c1f(n) +c2g(n)≤c3f(n)+c3g(n)=c3(f(n)+g(n))

≤c32max{f(n),g(n)}=2c3h(n)=O(max{f(n),g(n)})。

7.解:先将a 中元素递增排序,再求出现次数最多的次数maxnum,最后判断是否满足条件。对应的程序如下:

#include <stdio.h>

#include <algorithm>

using namespace std;

2

第1章

概论

boolsolve(inta[],intn,int&x)

{sort(a,a+n);

int maxnum=0;

int num=1;

int e=a[0];

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

{if (a[i]==e)

{num++;

//递增排序

//出现次数最多的次数

if (num>maxnum)

{maxnum=num;

x=e;

}

}

else

{e=a[i];

num=1;

}

}

if (maxnum>n/2)

return true;

else

return false;

}

voidmain()

{int a[]={2,2,2,4,5,6,2};

int n=sizeof(a)/sizeof(a[0]);

int x;

if (solve(a,n,x))

printf("出现次数超过所有元素一半的元素为%d\n",x); else

printf("不存在出现次数超过所有元素一半的元素\n");

}

上述程序的执行结果如图1.1 所示。

图1.1

程序执行结果

8.解:采用前后字符判断方法,对应的程序如下:#include <iostream>

#include <string>

using namespace std;

boolsolve(stringstr)//判断字符串str是否为回文{int i=0,j=str.length()-1;

while (i<j)

{if (str[i]!=str[j])

return false;

3

算法设计

i++; j--;

}

return true;

}

voidmain()

{cout << "求解结果"<<endl;

string str="abcd";

cout << "" << str<<(solve(str)?"是回文":"不是回文")<< endl; string str1="abba";

cout << "" << str1<<(solve(str1)?"是回文":"不是回文")<<endl;}

上述程序的执行结果如图1.2所示。

图1.2

程序执行结果

9.解:先将a 中元素递增排序,然后从两端开始进行判断。对应的程序如下:#include <stdio.h>

#include <algorithm>

using namespace std;

boolsolve(inta[],intn,intk)

{sort(a,a+n);

int i=0, j=n-1;

while (i<j)

{if (a[i]+a[j]==k)

return true;

//递增排序

//区间中存在两个或者以上元素

else if (a[i]+a[j]<k)

i++;

else

j--;

}

return false;

}

voidmain()

{int a[]={1,2,4,5,3};

int n=sizeof(a)/sizeof(a[0]);

printf("求解结果\n");

int k=9,i,j;

if (solve(a,n,k,i,j))

printf("存在: %d+%d=%d\n",a[i],a[j],k);else

printf("不存在两个元素和为%d\n",k);

int k1=10;

if (solve(a,n,k1,i,j))

printf("存在: %d+%d=%d\n",a[i],a[j],k1);

4

第1章

概论

else

printf("

不存在两个元素和为%d\n",k1);

}

上述程序的执行结果如图1.3 所示。

图1.3

程序执行结果

10.解:采用集合set<int>存储整数序列,集合中元素默认是递增排序的,再采用二路归并算法求它们的交集。对应的程序如下:

#include <stdio.h>

#include <set>

using namespace std;

voidsolve(set<int>s1,set<int>s2,set<int>&s3){set<int>::iteratorit1,it2;

it1=s1.begin(); it2=s2.begin();

while (it1!=s1.end()&& it2!=s2.end())

{if (*it1==*it2)

{s3.insert(*it1);

++it1; ++it2;

}

else if (*it1<*it2)

++it1;

else

++it2;

}

}

//求交集s3

voiddispset(set<int>s)

{set<int>::iteratorit;

//输出集合的元素

for (it=s.begin();it!=s.end();++it)

printf("%d ",*it);

printf("\n");

}

voidmain()

{int a[]={3,2,4,8};

int n=sizeof(a)/sizeof(a[0]);

set<int> s1(a,a+n);

int b[]={1,2,4,5,3};

int m=sizeof(b)/sizeof(b[0]);

set<int> s2(b,b+m);

set<int> s3;

solve(s1,s2,s3);

printf("求解结果\n");

printf("s1: ");dispset(s1);

5

算法设计

printf("

printf("

s2: "); dispset(s2);

s3: "); dispset(s3);

}

上述程序的执行结果如图1.4 所示。

图1.4

程序执行结果

11.解:对于正整数n,从i=2 开始查找其质因数,ic 记录质因数i 出现的次数,当找到这样质因数后,将(i,ic)作为一个元素插入到vector 容器v 中。最后输出v。对应的算法如下:

#include <stdio.h>

#include <vector>

using namespace std;

struct NodeType

{int p;

int pc;

//vector向量元素类型 //质因数

//质因数出现次数

};

voidsolve(intn,vector<NodeType>&v)//求n的质因数分解{int i=2;

int ic=0;

NodeType e;

do

{if (n%i==0)

{ic++;

n=n/i;

}

else

{if (ic>0)

{e.p=i;

e.pc=ic;

v.push_back(e);

}

ic=0;

i++;

}

} while (n>1 || ic!=0);

}

voiddisp(vector<NodeType>&v)//输出v

{vector<NodeType>::iteratorit;

for (it=v.begin();it!=v.end();++it)

printf("质因数%d出现%d次\n",it->p,it->pc);

}

6

第1章

概论

voidmain()

{vector<NodeType>v;

int n=100;

printf("n=%d\n",n);

solve(n,v);

disp(v);

}

上述程序的执行结果如图1.5 所示。

图1.5

程序执行结果

12.解:先递增排序,再求相邻元素差,比较求最小元素差,累计最小元素差的个数。对应的程序如下:

#include <iostream>

#include <algorithm>

#include <vector>

using namespace std;

intsolve(vector<int>&myv)

//求myv中相差最小的元素对的个数

{sort(myv.begin(),myv.end());//递增排序

int ans=1;

int mindif=myv[1]-myv[0];

for (int i=2;i<myv.size();i++)

{if (myv[i]-myv[i-1]<mindif)

{ans=1;

mindif=myv[i]-myv[i-1];

}

else if (myv[i]-myv[i-1]==mindif)

ans++;

}

return ans;

}

voidmain()

{int a[]={4,1,2,3};

int n=sizeof(a)/sizeof(a[0]);

vector<int> myv(a,a+n);

cout << "相差最小的元素对的个数:" << solve(myv) <<endl; }

上述程序的执行结果如图1.6 所示。

7

图1.6

算法设计

程序执行结果

13.解:对于map<string,int>容器mymap,设计另外一个map<int,int>容器tmap,将前者的value 作为后者的关键字。遍历mymap,累计tmap 中相同关键字的次数。一个参考程序及其输出结果如下:

#include <iostream>

#include <map>

#include <string>

using namespace std;

voidmain()

{map<string,int>mymap;

mymap.insert(pair<string,int>("Mary",80));

mymap.insert(pair<string,int>("Smith",82));

mymap.insert(pair<string,int>("John",80));

mymap.insert(pair<string,int>("Lippman",95));

mymap.insert(pair<string,int>("Detial",82));

map<string,int>::iteratorit;

map<int,int> tmap;

for (it=mymap.begin();it!=mymap.end();it++)

tmap[(*it).second]++;

map<int,int>::iteratorit1;

cout << "求解结果"<<endl;

for (it1=tmap.begin();it1!=tmap.end();it1++)

cout << "" << (*it1).first<< ":" << (*it1).second<< "次\n";

}

上述程序的执行结果如图1.7 所示。

图1.7

程序执行结果

14.解:采用map<int,int>容器mymap 存放求解结果,第一个分量存放质因数,第二个分量存放质因数出现次数。对应的程序如下:

#include <stdio.h>

#include <map>

using namespace std;

voidsolve(intn,map<int,int>&mymap)//求n的质因数分解

{int i=2;

int ic=0;

do

{

if (n%i==0)

{ic++;

n=n/i;

}

8

第1章

概论

else

{if (ic>0)

mymap[i]=ic;

ic=0;

i++;

}

} while (n>1 || ic!=0);

}

voiddisp(map<int,int>&mymap)//输出mymap

{map<int,int>::iteratorit;

for (it=mymap.begin();it!=mymap.end();++it)

printf("质因数%d出现%d次\n",it->first,it->second);

}

voidmain()

{map<int,int>mymap;

int n=12345;

printf("n=%d\n",n);

solve(n,mymap);

disp(mymap);

}

上述程序的执行结果如图1.8 所示。

图1.8

程序执行结果

15.解:栈容器不能顺序遍历,为此创建一个临时tmpst 栈,将st 的k个元素出栈并进栈到tmpst 中,再出栈tmpst一次得到第k 个元素,最后将栈tmpst 的所有元素出栈并进栈到st 中。对应的程序如下:

#include <stdio.h>

#include <stack>

using namespace std;

intsolve(stack<int>&st,intk)

{stack<int> tmpst;

int e;

for (int i=0;i<k;i++)

{e=st.top();

st.pop();

tmpst.push(e);

}

e=tmpst.top();

tmpst.pop();

while (!tmpst.empty())

{st.push(tmpst.top());

tmpst.pop();

//出栈第k个元素

//出栈st的k个元素并进tmpst栈//求第k个元素

//将tmpst的所有元素出栈并进栈st9

}

return e;

}

voiddisp(stack<int>&st)

{while (!st.empty())

{printf("%d ",st.top());

st.pop();

}

printf("\n");

}

voidmain()

{stack<int> st;

算法设计

//出栈st的所有元素

printf("进栈元素1,2,3,4\n");st.push(1);

st.push(2);

st.push(3);

st.push(4);

int k=3;

int e=solve(st,k);

printf("出栈第%d个元素是: %d\n",k,e);printf("st中元素出栈顺序: "); disp(st);

}

上述程序的执行结果如图1.9 所示。

图1.9

程序执行结果

1.2第2 章─递归算法设计技术

1.2.1练习题

1.什么是直接递归和间接递归?消除递归一般要用到什么数据结构?2.分析以下程序的执行结果:

#include <stdio.h>

voidf(intn,int&m)

{if (n<1) return;

else

{

}

printf("调用f(%d,%d)前,n=%d,m=%d\n",n-1,m-1,n,m);n--; m--;

f(n-1,m);

printf("调用f(%d,%d)后:n=%d,m=%d\n",n-1,m-1,n,m);

10

第1章

概论

}

voidmain()

{int n=4,m=4;

f(n,m);

}

3.采用直接推导方法求解以下递归方程:T(1)=1

T(n)=T(n-1)+n当n>1

4.采用特征方程方法求解以下递归方程:H(0)=0

H(1)=1

H(2)=2

H(n)=H(n-1)+9H(n-2)-9H(n-3)当n>2 5.采用递归树方法求解以下递归方程:T(1)=1

T(n)=4T(n/2)+n当n>1

6.采用主方法求解以下题的递归方程。

T(n)=1

当n=1

T(n)=4T(n/2)+n当n>1

7.分析求斐波那契f(n)的时间复杂度。

8.数列的首项a1=0,后续奇数项和偶数项的计算公式分别为a2n=a2n-1+2,a2n+1=a2n- 1+a2n-1,写出计算数列第n项的递归算法。

9.对于一个采用字符数组存放的字符串str,设计一个递归算法求其字符个数(长度)。

10.对于一个采用字符数组存放的字符串str,设计一个递归算法判断str 是否为回文。

11.对于不带头结点的单链表L,设计一个递归算法正序输出所有结点值。

12.对于不带头结点的单链表L,设计一个递归算法逆序输出所有结点值。

13.对于不带头结点的非空单链表L,设计一个递归算法返回最大值结点的地址(假设这样的结点唯一)。

14.对于不带头结点的单链表L,设计一个递归算法返回第一个值为x 的结点的地址,没有这样的结点时返回NULL。

15.对于不带头结点的单链表L,设计一个递归算法删除第一个值为x 的结点。

16.假设二叉树采用二叉链存储结构存放,结点值为int 类型,设计一个递归算法求二叉树bt 中所有叶子结点值之和。

17.假设二叉树采用二叉链存储结构存放,结点值为int 类型,设计一个递归算法求二叉树bt 中所有结点值大于等于k 的结点个数。

18.假设二叉树采用二叉链存储结构存放,所有结点值均不相同,设计一个递归算法求值为x 的结点的层次(根结点的层次为1),没有找到这样的结点时返回0。

11

算法设计

1.2.2练习题参考答案

1.答:一个f 函数定义中直接调用f 函数自己,称为直接递归。一个f 函数定义中调用g 函数,而g 函数的定义中调用f 函数,称为间接递归。消除递归一般要用栈实现。

2.答:递归函数f(n,m)中,n是非引用参数,m是引用参数,所以递归函数的状态为(n)。程序执行结果如下:

调用f(3,3)前,n=4,m=4

调用f(1,2)前,n=2,m=3

调用f(0,1)后,n=1,m=2

调用f(2,1)后,n=3,m=2

3.解:求T(n)的过程如下:

T(n)=T(n-1)+n=[T(n-2)+n-1)]+n=T(n-2)+n+(n-1)

=T(n-3)+n+(n-1)+(n-2)

=…

=T(1)+n+(n-1)+…+2

=n+(n-1)+ +…+2+1=n(n+1)/2=O(n)。

4.解:整数一个常系数的线性齐次递推式,用x

n-33232

代替H(n),有:x=x+9x-9x,

x-x-9x+9=x(x-9)-(x-9)=(x-1)(x-9)=(x-1)(x+3)(x-3)=0。得到r1=1,r2=-3,r3=3则递归方程的通解为:H(n)=c1+c2(-3)+c33

代入H(0)=0,有c1+c2+c3=0

代入H(1)=1,有c1-3c2+3c3=1

代入H(2)=2,有c1+9c2+9c3=2

求出:c1=-1/4,c2=-1/12,c3=1/3,H(n)=c1+c2(-3)+c33=(

n‒1

4

+ 13

1

‒。

5.解:构造的递归树如图1.10 所示,第1 层的问题规模为n,第2 的层的子问题的问题规模为n/2,依此类推,当展开到第k+1层,其规模为n/2=1,所以递归树的高度为log2n+1。

第1层有1个结点,其时间为n,第2层有4个结点,其时间为4(n/2)=2n,依次类推,第k 层有4个结点,每个子问题规模为n/2,其时间为4(n/2)=2n。叶子结点的个数为n 个,其时间为n。将递归树每一层的时间加起来,可得:

logn

T(n)=n+2n+…+ 2n+…+n≈

算法设计与分析(李春保)练习题答案v1的更多相关文章

  1. 算法设计与分析(李春保)练习题答案v2

    ----------------------------------------------------- Page 1 --------------------------------------- ...

  2. 算法设计与分析 - AC 题目 - 第 5 弹(重复第 2 弹)

    PTA-算法设计与分析-AC原题 - 最大子列和问题 (20分) 给定K个整数组成的序列{ N1, N2, ..., NK },“连续子列”被定义为{ Ni, Ni+, ..., Nj },其中 ≤i ...

  3. 算法设计与分析 - AC 题目 - 第 2 弹

    PTA-算法设计与分析-AC原题7-1 最大子列和问题 (20分)给定K个整数组成的序列{ N1, N2, ..., NK },“连续子列”被定义为{ Ni, Ni+1, ..., Nj },其中 1 ...

  4. 【技术文档】《算法设计与分析导论》R.C.T.Lee等·第7章 动态规划

    由于种种原因(看这一章间隔的时间太长,弄不清动态规划.分治.递归是什么关系),导致这章内容看了三遍才基本看懂动态规划是什么.动态规划适合解决可分阶段的组合优化问题,但它又不同于贪心算法,动态规划所解决 ...

  5. 算法设计与分析-Week12

    题目描述 You are given coins of different denominations and a total amount of money amount. Write a func ...

  6. 算法设计与分析 - 李春葆 - 第二版 - pdf->word v3

    1.1 第1章─概论 练习题 . 下列关于算法的说法中正确的有( ). Ⅰ.求解某一类问题的算法是唯一的 Ⅱ.算法必须在有限步操作之后停止 Ⅲ.算法的每一步操作必须是明确的,不能有歧义或含义模糊 Ⅳ. ...

  7. 算法设计与分析 - 李春葆 - 第二版 - html v2

    1 .1 第 1 章─概论   1.1.1 练习题   1 . 下列关于算法的说法中正确的有( ).   Ⅰ Ⅱ Ⅲ Ⅳ .求解某一类问题的算法是唯一的   .算法必须在有限步操作之后停止   .算法 ...

  8. 算法设计与分析 - 李春葆 - 第二版 - pdf->word v1

    章─概论 练习题 . 下列关于算法的说法中正确的有( ).Ⅰ.求解某一类问题的算法是唯一的 Ⅱ.算法必须在有限步操作之后停止 Ⅲ.算法的每一步操作必须是明确的,不能有歧义或含义模糊Ⅳ.算法执行后一定产 ...

  9. 南大算法设计与分析课程复习笔记(1) L1 - Model of computation

    一.计算模型 1.1 定义: 我们在思考和处理算法的时候是机器无关.实现语言无关的.所有的算法运行在一种“抽象的机器”之上,这就是计算模型. 1.2 种类 图灵机是最有名的计算模型,本课使用更简单更合 ...

随机推荐

  1. QML MouseArea学习小结

    QML中的MouseArea类型为用户进行简单的鼠标操作提供了方便. MouseArea是一个不可见的Item,通常与可见项目结合使用,以便为该项目提供鼠标处理.通过有效地充当代理,鼠标处理的逻辑可以 ...

  2. Atlassian JIRA服务器模板注入漏洞复现(CVE-2019-11581)

    0x00 漏洞描述 Atlassian Jira是澳大利亚Atlassian公司的一套缺陷跟踪管理系统.该系统主要用于对工作中各类问题.缺陷进行跟踪管理. Atlassian Jira Server和 ...

  3. 简单几招提速 Kotlin Kapt编译

    https://droidyue.com/blog/2019/08/18/faster-kapt/?hmsr=toutiao.io&utm_medium=toutiao.io&utm_ ...

  4. SQOOP的使用方法

    Sqoop是个命令行工具,用来在Hadoop和rdbms之间传输数据. 以Hadoop的角度看待数据流向,从rdbms往Hadoop是导入用sqoop import命令,反之从hadoop往rdbms ...

  5. AIX—日常运维命令总结

    1. 查看AIX服务器的物理构造信息,包括服务器网络配置信息 # prtconf # ifconfig -a # lsattr -E -l mem0 :查看系统内存大小 # netstat -in : ...

  6. OpenSSL生成私钥和公钥

    1.生成私钥 -- 生成 RSA 私钥(传统格式的) openssl genrsa -out rsa_private_key.pem 1024 -- 将传统格式的私钥转换成 PKCS#8 格式的(JA ...

  7. ChengDu University Mental Health Test 需求分析文档

    ChengDu University Mental Health Website 需求分析文档 V4.0 编制人:刘雷,黄凯 日期:2019/4/28 版本修订历史记录: 版本 日期 修改内容 作者 ...

  8. win10台式机rtl8188eu(FW 150 UM V2.0)无线网卡无法连接wifi(无法连接到这个网络)

    同一个网卡,同一个WiFi,在笔记本上能用,能连接wifi,但是在台式机上就不能连接wifi,提示“无法连接到这个网络”,如下图. win10版本都是1903.尝试换各种驱动都没解决. 最后更新主板b ...

  9. WTL 9.0的变化 - atlapp.h

    忽然发现WTL更新到9.0.4140了,便对比了一下 8.1.12085. 先看看atlapp.h中有什么大的变动. 第61行: #if defined(_SYSINFOAPI_H_) &&a ...

  10. linux 以导入文件形式添加定时任务(crontab)时需要注意的坑

    在实际操作过程中发现,使用导入文件形式添加定时任务时,会将用户已有的定时任务全部覆盖清理(先清空,再重新导入),所以在使用文件导入定时任务时,需要先将已有定时任务导出,然后将新任务进行追加到已有定时任 ...