递归概念专题

暴力递归

一:基础知识:暴力递归就是尝试出所有的方案。
1.1:递归的过程和伪代码模版

  • 有明确的不需要继续进行递归的条件(basecase)
  • 把问题转化为规模缩小了的同类问题的子问题
  • 确定当得到了子问题的结果之后的决策过程
int/void process(一个或者两个变化参数和一些不变的参数) {
	if(end_condition) {//递归结束的条件和basecase是一致的,有2种理解方式
		end;//结束情境
		return; //return value;
	}
	slove();//递归前的处理方式,递过程进去
	process(变化参数变化,不变参数不变);//大规模问题转小规模问题
	solve();//递归后的处理,归过程
	return;//return value;
}

二:递归问题的思路步骤
2.1:递归能解决的问题(判断问题是否能够递归解决)

  • 1.打印机器人运动路径,输出全排列,dfs遍历。。(跟路径有关的仅能递归解决)
  • 2.求方法数一个值,求最大最小值,是否存在(既可以递归,又可以dp,还可以记忆搜索)
  • 3 递归(自顶向下)(if(存在重复计算))----->记忆化搜索(自顶向下)(每次计算存memo数组)—>dp(自下向顶)

2.2:确定递归模型,并画出思维树或者图(即找到一种方法能够用尝试所有过程)
递归常用的四种模型:**

  • 从左到右的尝试模型(int index):arr[i]选择不选择,空位有哪几种选择,该位置是否与后续交换
  • 范围上的尝试模型(int left ,int right)
  • 多样本位置全对应的尝试模型(string a,string b)
  • 寻找业务限制的尝试模型

2.3:明确递归函数的作用(也就是问题所求),并且确定好递归参数(可以编写code边添加确定),带入参数再次确定递归函数作用

2.4:basecase 2种理解,一种是递归的变化参数的终止条件,二是基本案例情况下的返回值,二者统一

2.5:递过程的操作

2.6:递归的调用:参数规模变小,同时还设计到思维树是否同层需要剪枝,多种选择的情况下回溯等(由问题的限制条件决定的)

2.7:归过程的操作

2.8:return ;或者return value;

三:递归常考问题
1.汉罗塔问题

#include<iostream>
using namespace std;
#include<vector>
#include<string>

class Solution {
public:
	void hans(int n, string A, string B, string C, int& steps ) {
		if (n == 0) return;
		if (n == 1) {
			cout << " move " << n << " from " << A << " to " << C << endl;;
			steps++;
			return;
		}
		hans(n - 1, A, C, B, steps);//将A上面n-1个通过C移到B
		cout << " move " << n << " from " << A << " to " << C << endl;//将A最后一个移到C
		steps++;
		hans(n - 1, B, A, C, steps);//将B上面n-1个通过空的A移到C
	}


};

int main()
{
	int steps = 0;
	Solution slt;
	slt.hans(3, "A", "B", "C",steps);
	cout << steps << endl;
	system("pause");
	return 0;
}

//给定一个长度为 n 的可包含重复数字的序列,从中随机选取 m 个数字,输出所有可能的选择方案。
//
//输入格式
//第一行包含两个整数 n, m。
//
//第二行包含 n 个正整数。
//
//输出格式
//按照从小到大的顺序输出所有方案,每行 1 个。
//
//首先,同一行内的数升序排列,相邻两个数用一个空格隔开。
//
//其次,对于两个不同的行,对应下标的数一一比较,字典序较小的排在前面(例如1 3 5 7排在1 3 6 8前面)。
//
//数据范围
//n>0,
//0≤m≤n,
//n + (n−m)≤25,
//序列内所有元素均不大于 n。
//
//输入样例:
//5 3
//1 2 2 3 3
//输出样例:
//1 2 2
//1 2 3
//1 3 3
//2 2 3
//2 3 3
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

void process(vector<int>arr, int m, int index, int arrindex, vector<int>path) {
	if (index == m) {
		for (int i : path) cout << i << " ";
		cout << endl;
		return;
	}
	if (arrindex >= arr.size()) return;
	vector<bool>used(arr.size(), false);
	for (int i = arrindex; i<arr.size(); i++) {
		if (used[arr[i]] == false) {
			used[arr[i]] = true;
			path.push_back(arr[i]);
			process(arr, m, index + 1, i + 1, path);
			path.pop_back();
		}
	}
}

int main() {
	int n, m;
	cin >> n >> m;
	vector<int>arr(n);
	for (int i = 0; i<n; i++) cin >> arr[i];
	sort(arr.begin(), arr.end());
	vector<int>path;
	process(arr, m, 0, 0, path);
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值