个人学习笔记。
1、空间使用:printN函数的实现。
#include "stdafx.h"
void printN(int n)
{
for (int i = 1; i <= n; ++i)
{
printf("%d\n", i);
}
}
void printN(int n)
{
if (n>=1)
{
printN(n - 1);
printf("%d\n", n);
}
}
int _tmain(int argc, _TCHAR* argv[])
{
printN(10000);
return 0;
}
递归调用在每一次递归时需要将前一个函数调用的状态保存,输出1~10000时,在输出1之前存储了9999个函数的状态,空间不足爆掉了。
2、算法效率:计算多项式的值
多项式:
秦九韶算法:
#include "stdafx.h"
#include<math.h>
#include<time.h>
#define MAXN 10//多项式的项数
#define MAXK 10000//重复计算次数
double f1(int n, double a[], double x)
{
double ret = a[0];
for (int i = 1; i <= n;++i)
{
ret += a[i] * pow(x, i);
}
return ret;
}
//秦九韶算法
double f2(int n, double a[], double x)
{
double ret = a[n];
for (int i = n; i > 0;--i)
{
ret = a[i - 1] + ret*x;
}
return ret;
}
int _tmain(int argc, _TCHAR* argv[])
{
clock_t start, stop;
double duration;
double a[MAXN];
double ret;
for (int i = 0; i < MAXN;++i)
{
a[i] = (double)i;
}
start = clock();
for (int i = 0; i < MAXK; ++i)
{
ret = f1(MAXN, a, 1.01);
}
stop = clock();
duration = (double)(stop - start) / CLK_TCK / MAXK;
printf("duration1=%6.2e\n", duration);//控制格式,输出最小宽度为6,精度为2,e为以指数形式输出
start = clock();
for (int i = 0; i < MAXK; ++i)
{
ret = f2(MAXN, a, 1.01);
}
stop = clock();
duration = (double)(stop - start) / CLK_TCK / MAXK;
printf("duration2=%6.2e\n", duration);
return 0;
}
3、最大子列和
#include "stdafx.h"
#include<time.h>
#define MAXK 10000//重复计算次数
int maxSubseqSum1(int a[], int n)
{
int max_sum = 0, this_sum;
for (int i = 0; i < n;++i)
{
for (int j = i; j < n;++j)
{
this_sum = 0;
for (int k = i; k <= j;++k)
{
this_sum += a[k];
}
if (this_sum>max_sum)
{
max_sum = this_sum;
}
}
}
return max_sum;
}
//暴力解法,求出所有子列和,时间复杂度O(N^2)
int maxSubseqSum2(int a[], int n)
{
int max_sum = 0, this_sum;
for (int i = 0; i < n;++i)
{
this_sum = 0;
for (int j = i; j < n;++j)
{
this_sum += a[j];
if (this_sum>max_sum)
{
max_sum = this_sum;
}
}
}
return max_sum;
}
//求三数最大值
int Max3(int a, int b, int c)
{
return a>b ? (a > c ? a : c) : (b > c ? b : c);
}
//分治思想求解,二分数列,求左右最大子列(递归)和及中间子列和,进行比较
int DivideAndConquer(int list[], int left, int right)
{
int max_left = 0, max_right = 0;//左右子列最大和
int max_leftbor = 0, max_rightbor = 0;//中心边界左右两边最大子列和
int leftbor = 0, rightbor = 0;
//递归终止条件
if (left==right)
{
if (list[left]>0)
{
return list[left];
}
else
{
return 0;
}
}
int center = (left + right) / 2;
//递归计算左右两边最大子列和
max_left = DivideAndConquer(list, left, center);
max_right = DivideAndConquer(list, center + 1, right);
//计算中心边界左右两边的最大子列和
for (int i = center; i >= left;--i)
{
leftbor += list[i];
if (leftbor>max_leftbor)
{
max_leftbor = leftbor;
}
}
for (int i = center+1; i <= right;++i)
{
rightbor += list[i];
if (rightbor>max_rightbor)
{
max_rightbor = rightbor;
}
}
return Max3(max_left, max_right, max_leftbor + max_rightbor);
}
//保持函数形参的一致,时间复杂度O(NlogN),递归要考虑空间复杂度
int maxSubseqSum3(int a[], int n)
{
return DivideAndConquer(a, 0, n - 1);
}
//在线处理,一直向右累加,如果比最大值大就更新最大值,如果小于0,则重新开始累加,时间复杂度O(N)
int maxSubseqSum4(int a[], int n)
{
int max_sum = 0, this_sum = 0;
for (int i = 0; i < n;++i)
{
this_sum += a[i];
if (this_sum<0)
{
this_sum = 0;
}
if (this_sum > max_sum)
{
max_sum = this_sum;
}
}
return max_sum;
}
//计算函数运行耗时
void computeTime(int(*pf)(int a[], int n))
{
clock_t start, stop;
double duration;
int arr[10] = { 3, -1, 5, 7, -9, 5, 2, 1, -2, 4 };
int ret;
start = clock();
for (int i = 0; i < MAXK; ++i)
{
ret = (*pf)(arr, 10);
}
stop = clock();
duration = (double)(stop - start) / CLK_TCK / MAXK;
printf("duration=%6.2e\n", duration);//控制格式,输出最小宽度为6,精度为2,e为以指数形式输出
}
int _tmain(int argc, _TCHAR* argv[])
{
computeTime(maxSubseqSum1);
computeTime(maxSubseqSum2);
computeTime(maxSubseqSum3);
computeTime(maxSubseqSum4);
return 0;
}
4、对分查找
#include "stdafx.h"
#include<iostream>
#define MAXSIZE 10
#define NotFound 0
typedef int ElementType;
using namespace std;
typedef int Position;
typedef struct LNode *List;
struct LNode {
ElementType Data[MAXSIZE];
Position Last; /* 保存线性表中最后一个元素的位置 */
};
Position BinarySearch(List L, ElementType X)
{
Position mid;
Position low = 1, high = L->Last;
while (low<=high)
{
mid = (high - low) / 2 + low;
if (X>(L->Data)[mid])
{
low = mid + 1;
}
else if (X < (L->Data)[mid])
{
high = mid - 1;
}
else
return mid;
}
return NotFound;
}
int _tmain(int argc, _TCHAR* argv[])
{
LNode node;
List L = &node;
ElementType X;
Position P;
int N;
cin >> N;
for (int i = 1; i <= N;++i)
{
cin>>(L->Data)[i];
}
L->Last = N;
cin >> X;
P = BinarySearch(L, X);
printf("%d\n", P);
return 0;
}
5、最大公因子(公约数)
欧几里得算法(辗转相除法)
gcd(a,b)=gcd(b,a mod b):a,b的公约数与b,a mod b的公约数相等。
证明:设a>=b,则a=kb+r,r=a%b
假设d为a,b的公约数,则d|a,d|b,得d|a-kb,即d|r,d|a%b(|为整除)
所以d为b与a mod b的公约数。
#include "stdafx.h"
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
//得到input的所有因子并存入rvec中
void getFactor(int input, vector<int>& rvec)
{
auto n = input;
for (auto i = 1; i <= n;++i)
{
if (input%i == 0)
{
rvec.push_back(i);
rvec.push_back(input / i);
n = input / i - 1;
}
}
}
//得到a与b中最大的相等数,返回该数(a、b升序排列)
int getMaxEqual(vector<int>& a, vector<int>& b)
{
sort(a.begin(), a.end());
sort(b.begin(), b.end());
auto it1 = a.begin();
auto it2 = b.begin();
int max_eq;
bool isFind = false;
while (it1!=a.end()&&it2!=b.end())
{
if (*it1==*it2)
{
isFind = true;
max_eq = *it1;
++it1, ++it2;
}
else if (*it1<*it2)
{
++it1;
}
else
{
++it2;
}
}
if (it1==a.end())
{
while (it2!=b.end()&&*it2<=*(a.end()-1))
{
if (*it2 == *(a.end() - 1))
{
max_eq = *it2;
}
++it2;
}
}
else if (it2 ==b.end())
{
while (it1 != a.end() && *it1 <= *(b.end() - 1))
{
if (*it1 == *(b.end() - 1))
{
max_eq = *it1;
}
++it1;
}
}
return max_eq;
}
//对较小数遍历,看是否能被大数和小数同时整除
int getCommFactor1(int a, int b)
{
int n, max_eq = 1,i;
if (a>b)
{
n = b;
}
else
{
n = a;
}
for (i = 1; i <= n;++i)
{
if ((a%i==0)&&(b%i==0)&&(i>max_eq))//求余耗时
{
max_eq = i;
}
}
return max_eq;
}
//分别计算两数因子,找出因子中的最大相等数
int getCommFactor2(int a, int b)
{
vector<int> a_fac, b_fac;
getFactor(a, a_fac);
getFactor(b, b_fac);
return getMaxEqual(a_fac, b_fac);
}
//欧几里得算法计算最大公因子
//0除以任何数均为0,0与任何数的最大公约数为这个数
//一直求余,当b=0时,最大公约数就是a
int getCommFactor3(int a, int b)
{
//异或实现交换两数
if (a<b)
{
a = a^b;//a^b得到a b不同位为1,相同位为0
b = a^b;//b与a异或,将a中为1对应的位反转,得到原来的b(与1异或反转,与0异或不变)
a = a^b;//将a(现在为原来的a)变为原来的b
}
int temp;
while (b>0)
{
temp = a%b;
a = b;
b = temp;
}
return a;
}
int _tmain(int argc, _TCHAR* argv[])
{
int a, b, comm_factor;;
cin >> a >> b;
comm_factor = getCommFactor1(a, b);
cout << "getCommFactor1: " << comm_factor << endl;
comm_factor = getCommFactor2(a, b);
cout << "getCommFactor2: " << comm_factor << endl;
comm_factor = getCommFactor3(a, b);
cout << "getCommFactor3: " << comm_factor << endl;
return 0;
}
6、计算一个整数X的N次幂
#include "stdafx.h"
#include<iostream>
using namespace std;
long long powN(long long x, unsigned int n)
{
if (n==0)
{
return 1;
}
if (x&1==0)//x为偶数,偶数的最后一位必为0,与1位与得0
{
return powN(x*x, n / 2);
}
else
{
return powN(x*x, n / 2)*x;
}
}
int _tmain(int argc, _TCHAR* argv[])
{
long int x;
unsigned int n;
cin >> x >> n;
cout << powN(x, n) << endl;
return 0;
}