递归

本文详细探讨了递归的概念,并通过实例介绍了阶乘、斐波那契数列的递归与循环实现,解析了全排列算法的逻辑,还讨论了数组所有子集的生成。同时,文章比较了递归中i+1,i++,++i及引用i在递归调用中的不同行为。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

递归:

(1)直接或间接的调用自身的算法
(2)使用函数自身给出的定义

1. 阶乘

循环实现阶乘
时间复杂度:O(n)
空间复杂度:S(1)

int fun(int n)
{
	int sum = 1;
	for(int i = 1; i <= n; ++i)
	{
		 sum = sum * i;
		 if(sum < 0) return -1;
	}
	return sum;
}

递归实现阶乘
时间复杂度:O(2^n)
空间复杂度:S(n)

int fan(int n)
{
	if(n <= 1)
		return 1;
	else
		return fan(n - 1) * n;
}

2. 斐波那契数列

递归实现斐波那契数列
时间复杂度:O(2^n)
空间复杂度:S(n)

int fun1(int n)
{
	if(n <= 2)
		return 1;
	if(n > 2)
		return fun1(n - 1) + fun1(n - 2);
}

循环实现斐波那契数列
时间复杂度:O(n)
空间复杂度:S(1)

int fan1(int n)
{
	int a = 1, b = 1, c = 1;
	for(int i = 3; i <= n; i++)
	{
		c = a + b;
		b = a;
		a = c;
	}
	return c;
}

3. 全排列

可参考 https://blog.youkuaiyun.com/hushhw/article/details/78112719
算法思路:
    (1) n 个元素的全排列 =(n-1 个元素的全排列)+(另一个元素作为前缀);
    (2)出口:如果只有一个元素的全排列,则说明已经排完,则输出数组;
    (3)不断将每个元素放作第一个元素,然后将这个元素作为前缀,并将其余元素继续全排列,等到出口,出口出去后还需要还原数组;
如对1、2、3进行全排序
1 为前缀,对 2 和 3 进行排序,结果为 123、132。把 1 和 2 进行交换得到 2 1 3
2 为前缀,对 1 和 3 进行全排序,结果为 213、231。把 1 和 3 进行交换得到 3 2 1
3 为前缀,对 2 和 1 进行全排序,结果为 321、312。

void Perm(int *arr, int k, int m)
{
	if(k == m)
	{
		for(int i = 0; i <= m; ++i)
		{
			cout << arr[i] << " ";
		}
		cout<<endl;
	}
	else
	{
		for(int j =k; j <= m; j++)
		{
			swap(arr[j], arr[k]);
			Perm(arr, k + 1, m);
			swap(arr[j], arr[k]);
		}
	}
}

4. 数组的所有子集

数组 ar[ ] = {1,2,3},其子集有
  ar[ ] = {1 2 3}
子集为0 0 0
           0 0 1
           0 1 1
           1 0 0
           1 0 1
           1 1 0
           1 1 1
在这里插入图片描述

void fun2(int *arr,int *brr,int i, int n)
 {
	 if(i >= n)
	 {
		 for(int j = 0;j < n; ++j)
		 {
			 if(brr[j])
			 {
				 cout<< arr[j]<< " ";
			 }
		 }
		 cout <<endl;
	 }
	 else
	 {
		 brr[i] = 1;
		 fun2(arr, brr, i+1, n);//left
		 brr[i] = 0;
		 fun2(arr, brr, i+1, n);//right
	 }
 }

5. 比较

比较递归中的 i+1,i++,++i,&i 的区别
(1)i+1
      第一次调用 fun(i+1, n), i+1,i本身的值没有变化,第二次调用 fun(i+1, n) 时,i本身的值没有变化,因此两次调用 fun(i, n) 时,i的值没有变化
在这里插入图片描述

 void fun3(int i, int n)
 {
	 if(i >= n)
	 {
		 cout <<i <<endl;
	 }
	 else
	 {
		 fun3(i+1, n);
		 fun3(i+1, n);
	 }
 }

(2)i++
       i是先调用 fun(i, n) 再进行 ++,但是之后调用的依旧是 fun(i, n),而不是 fun(i++, n),所以就陷入了死循环
在这里插入图片描述

void fun3(int i, int n)
 {
	 if(i >= n)
	 {
		 cout <<i <<endl;
	 }
	 else
	 {
		 fun3(i++, n);
		 fun3(i++, n);
	 }
 }

(3)++i
       调用 fun(i, n),i 先进行 ++,再进行调用。下一次调用时,依旧是先 ++,再调用
在这里插入图片描述

 void fun3(int i, int n)
 {
	 if(i >= n)
	 {
		 cout <<i <<endl;
	 }
	 else
	 {
		 fun3(++i, n);
		 fun3(++i, n);
	 }
 }

(4)&i
       调用 fun(i, n),i 先 ++,因为 i 被引用,所以,每次 ++ 之后前面调用的 i 的值就变成了 ++ 之后的值。
在这里插入图片描述

 void fun3(int &i, int n)
 {
	 if(i >= n)
	 {
		 cout <<i <<endl;
	 }
	 else
	 {
		 fun3(++i, n);
		 fun3(++i, n);
	 }
 }
int main()
{
	int i = 0, n = 3;
	fun3(i,n);
	return 0;
}

(5)&i,i+1
对 i 进行引用,要加 const 去常性
结果为 3 3 3 3 3 3 3 3

 void fun3(const int &i, int n)
 {
	 if(i >= n)
	 {
		 cout <<i <<endl;
	 }
	 else
	 {
		 fun3(i+1, n);
		 fun3(i+1, n);
	 }
 }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值