递归与递推学习
代码记录
/*递推【优于递归,减少重复工作】*/
//一·斐波拉契数列 A(n)=A(n-1)+A(n-2),输入整数第n月,输出每月兔子【1 1 2 3 5 8....】
//使用数组储存每一次结果,而不是函数自己执行自己
//#include<stdio.h>
//int main(){
// int a[10] = {0};//声明数组,60比50稍微大一点,避免数组越界
// int n;
// scanf("%d",&n);
// a[1] = 1;
// a[2] = 1;
// for(int i=3;i<=n;i++){//之前忘记改数据了,i = 3,如果i = 0,编译器将会产生不可知的行为
/*在编程中,每个程序都有自己的内存空间,这个空间被分为几个部分,比如栈(stack)、堆(heap)和静态存储区(static storage)。当你声明一个变量时,编译器会为这个变量分配一块内存,这块内存是属于你的程序的。
但是,如果你尝试访问一块不属于你的程序的内存,那么就会发生“内存越界”或者“内存访问错误”。这通常发生在以下几种情况:
数组越界:比如你有一个大小为10的数组,但是你尝试访问数组的第11个元素(比如array[10]),那么你就会访问到不属于你的内存。
指针错误:如果你有一个指针,你没有正确地初始化它,然后你尝试通过这个指针访问内存,那么你可能会访问到不属于你的内存。
动态内存分配错误:如果你使用了动态内存分配(比如在C语言中使用malloc或new),但是你没有正确地管理这些内存,比如忘记释放或者释放了之后还尝试访问,那么你可能会访问到不属于你的内存。
当你访问到不属于你的内存时,可能会导致以下几种结果:
程序崩溃:这是最常见的,因为操作系统会检测到你的程序正在尝试访问不属于它的内存,然后会终止你的程序。
数据损坏:如果你的程序修改了不属于它的内存,那么可能会导致其他程序或者操作系统的数据被破坏。
未定义行为:C语言标准将访问不属于你的内存定义为“未定义行为”,这意味着编译器可以做任何它想做的事情,比如什么也不做,或者让你的程序崩溃,或者让你的程序运行得很好,但是输出错误的结果。*/
// a[i] = a[i-1] + a[i-2];
//
// }
// for(int i=1;i<=n;i++){
// printf("%d\n",a[i]);
// }
// return 0;
//}
//二·小方块的堆积【递推式 A(n) = A(n-1) + n 输入一个整数n,显示A(1).....A(n)】
//#include<stdio.h>
//int main(){
//// int arr[] = {0};这里会出现数组越界,就是说自己后面输入一个值当作数组长度,之前不预判长度的话就会出现数组越界[这就是动态规划导致的数组越界]
///* 索引错误:最常见的原因是索引错误。例如,如果你的数组有10个元素,索引范围是0到9,但你尝试访问arr[10]或arr[-1],这就超出了数组的范围。
// 循环条件错误:在循环中处理数组时,如果循环的条件设置得不正确,可能会导致数组越界。例如,如果你的循环条件是i <= n,而数组的大小是n,那么当i等于n时,你将尝试访问arr[n],这会越界。
// 数组大小动态变化:在某些情况下,数组的实际大小可能会在程序运行时变化(例如,通过动态内存分配)。如果你没有正确地跟踪数组的大小,可能会导致越界。
// 用户输入:如果你的程序依赖于用户输入来确定数组的索引,而用户输入了一个超出范围的值,这也可能导致数组越界。
// 数组初始化错误:如果你没有正确地初始化数组,可能会访问到未初始化的内存。虽然这不一定是数组越界,但它可能导致未定义的行为,这通常与数组越界有关。*/
// int arr[50] = {0};
// int n = 0;
// scanf("%d",&n);
// arr[1]=1;
// for(int i=2;i<=n;i++){
// arr[i] = arr[i-1] + i;
// }
// for(int i=1;i<=n;i++){
// printf("%d\n",arr[i]);
// }
// return 0;
//}
//变式:显示一共有多少个方块
//#include<stdio.h>
//int main(){
// int n, sum = 0, ret;//一定要初始化sum!!!!!!!
// scanf("%d",&n);
// if(n == 1){
// printf("1");
// }else{
// for(int i=1;i<=n;i++){
// ret = 2 * i ;//就是找规律解决,反而没有例一难
// sum += ret;
// }printf("%d",sum);
// }
//
// return 0;
//}
//二.猴子吃桃子
//#include<stdio.h>
//int main(){
// int sum = 0;
// for(int i=1;i<=2;i++){
// sum = (i + 1) * 2;
// int ret = sum;
// printf("%d\n",sum);
// }
// printf("%d",sum);
// return 0;
//}
//!!!!没有缓存sum,循环又从i = 2,开始
//#include<stdio.h>
//int main(){
// int arr[20] = {0};
// arr[1] = 1;//要录入第一天桃子数据
// for(int i=2;i<=10;i++){
// arr[i] = (arr [i-1] + 1) * 2;
//// printf("%d",arr[i]);
// }
// printf("%d",arr[10]);
// return 0;
//}
//三·求解有规律的式子前n项和【1/1 +1/2 +2/3 +3/5 +5/8+... 输入整数n,输出小数,代表前n项和(保留三位小数)】
//递归法
//#include<stdio.h>
//int f(int n){
// int res = 0;
// if(n == 1||n ==2){
// return 1;
// }else{
// res += f(n-1) + f(n-2);
// return res;
// }
//}//计算分子
//int h(int n){
// int res = 0;
// if(n == 1){
// return 1;
// }else if(n == 2){
// return 2;//当时这里也出错了,有个else if
// }
// else{
// res += h(n-1) + h(n-2);//记住了,是两项的递归,怎么当时就写一项去了
// return res;
// }
//}//计算分母
//int main(){
// double arr[50]={0} ,sum = 0 ,n = 0;
// scanf("%lf",&n);
//// arr[1] = 1;
//// arr[2] = 1 / 2.0;
// for(int i=1;i<=n;i++){
// arr[i] = (double)f(i) / h(i);
// sum += arr[i];
//// printf("%f ",sum);
// }
// printf("%.3f",sum);
// return 0;
//}
//递推法
//#include<stdio.h>
//int main(){
// int arr[50] = {0},a[50] = {0} ,n = 0;
// double sum=0 ,ret = 0;
// scanf("%d",&n);
// arr[1] = 1;
// arr[2] = 1;
// a[1] = 1;
// a[2] = 2;
// if(n == 1){
// printf("1.000") ;
// }else if(n == 2){
// printf("1.500");
// }else{
// for(int i=3;i<=n;i++){
// arr[i] = arr[i-1] + arr[i-2];
// a[i] = a[i-1] + a[i -2];
// ret = (double) arr[i] / a[i];
// sum += ret ;
// }
// printf("%.3f",sum+3/2.0);//注意要分类讨论,不然前两项没有加到,而且一定注意 3/2 ==1!!!
// }
// return 0;
//}