习题纠错:
在下面的程序段中,对x的赋值语句的频度为: n(n+1)(n+2)/6 (表示为 n 的函数)
for(int i=1;i<=n;i++)
for(int j=1;j<=i;j++)
for(int k=1;k<=j;k++)
x=x+1;
最暴力的方法就是穷举,但是比较麻烦,在看到答案的时候其实就会有一种猜测:对于这种类型的for循环有 i 重频度就为:n * ( n + 1 ) * ...... * ( n + i - 1 )/ i!
特别的二重就是:n * (n + 1) / 2
三重就是:n * (n + 1) * (n + 2) / 6
四重就是:n * (n + 1) * (n + 2) * (n + 3) / 24
可以用数学归纳法证明一遍,但是为了方便直接通过下面代码的执行来直观的观察。(虽然只到了第五重)
// 时间复杂度.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
using namespace std;
void fuzadu1(int n) {
cout << n * (n + 1) * (n + 2) / 6 << endl;
int x = 0;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= i; j++) {
for (int k = 1; k <= j; k++) {
x++;
}
}
}
cout << x << endl;
}
void fuzadu2(int n) {
cout << n * (n + 1) * (n + 2) * (n + 3) / 24 << endl;
int x = 0;
for(int m=1;m<=n;m++)
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= i; j++) {
for (int k = 1; k <= j; k++) {
x++;
}
}
}
cout << x << endl;
}
void fuzadu3(int n) {
cout << n * (n + 1) * (n + 2) * (n + 3) * (n + 4) / (24 * 5) << endl;
int x = 0;
for (int z = 0; z <= n; z++)
for (int m = 1; m <= z; m++)
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= i; j++) {
for (int k = 1; k <= j; k++) {
x++;
}
}
}
cout << x << endl;
}
int main()
{
fuzadu1(10);
fuzadu2(10);
fuzadu3(10);
return 0;
}
1、设顺序表用数组A[]表示,表中元素存储在数组0~m+n-1 的范围内,前m个元素递增,后n个元素递增,设计 算法使整个设计表有序。
(1) 给出算法的基本设计思想。
(2) 根据设计思想,采用C或C++语言描述算法,并在关键之处给出注释。
(3) 说明你 所设计的算法的时间复杂度。
(1)给出算法的基本设计思想。
- 传参:数组A[],m表示前m个数,n表示共有n个数。
- 定义r表示数组B[]的下标,定义i,j为数组A[]下标。
- 将数组的A[ i ]同A[ j ]比较,小的存入数组B
- 若数组A的前m个数未遍历完,将剩余的数依次全部存入B
- 若数组A的后n个数未遍历完,将剩余的数依次全部存入B
(2)根据设计思想,采用C或C++语言描述算法,并在关键之处给出注释。
void merge(int A[],int m,int n) {
int B[max];
int r = 0;int i = 0; int j = m;
while (i < m && j < n) { //将数组的A[ i ]同A[ j ]比较,小的存入数组B
if (A[i] < A[j]) {
B[r++] = A[i++];
}
else {
B[r++] = A[j++];
}
}
while (i < m) { //若数组A的前m个数未遍历完,将剩余的数依次全部存入B
B[r++] = A[i++];
}
while (j < n) { //若数组A的后n个数未遍历完,将剩余的数依次全部存入B
B[r++] = A[j++];
}
for (int i = 0; i < r; i++) {
A[i] = B[i];
}
}
(3)说明你 所设计的算法的时间复杂度。
时间复杂度:O(n)
源码:
#include<iostream>
using namespace std;
#define eletype int
#define max 50
void init(int A[],int& m,int &n) {
for (int i = 0; i < 10; i++) {
A[i] = i * 2 + 1;
m++;
}
n += m;
for (int i = 10; i < 20; i++) {
A[i] = (i-10) * 2;
n++;
}
}
void printList(int A[],int n) {
for (int i = 0; i < n; i++) {
cout << A[i] << " ";
}
cout << endl;
}
void merge(int A[],int m,int n) {
int B[max];
int r = 0;int i = 0; int j = m;
while (i < m && j < n) {
if (A[i] < A[j]) {
B[r++] = A[i++];
}
else {
B[r++] = A[j++];
}
}
while (i < m) {
B[r++] = A[i++];
}
while (j < n) {
B[r++] = A[j++];
}
for (int i = 0; i < r; i++) {
A[i] = B[i];
}
}
int main() {
int A[max];
int n = 0;
int m = 0;
init(A,m,n);
printList(A,n);
merge(A,m,n);
printList(A, n);
return 0;
}
答案:
(1) 算法的基本设计思想:
将数组A [] 中的m+n个元素(假设元素为int型)看成两个顺序表:表L和表R。将数组当前状态看作是 起始状态,即此时表L由A[]中前m个元素构成,表R由A[]中后n个元素构成。要使A[]中m+n个元素整体有 序,只需将表R中的元素逐个插入表L中的合适位置即可。
插入过程:取表R中的第一个元素A[m+1]存入辅助变量temp中,让temp逐个与A[m],A[m1],...,A[1]进行比较,当temp<A[j](1≤j≤m)时,将A[j]后移一位,否则将temp存入A[j+1]中。重复 上述过程,继续插入A[m+1],A[m+3],...,A[m+n],最终A[]`中元素整体有序。
void SortArr(int A[],int m,int n) {
for (int i = m; i < m + n; i++) {
int temp = A[i];
for (int j = i - 1; j >= 0; j--) {
if (temp < A[j]) {
A[j + 1] = A[j];
}
else {
A[j + 1] = temp;
break; //note:不要忘记!!
}
}
}
}
(3) 算法的时间和空间复杂度
时间复杂度为O(mn)
空间复杂度为O(1)