1.把问题转化为规模缩小了的同类问题的子问题
2.有明确的不需要继续进行递归的条件
3.有当得到了子问题的结果之后的决策过程
4.不记录每一个子问题的解
【汉诺塔问题】
void func(int n, string from, string to, string other){
if(n == 1){
cout << "Move 1 from " << from << " to " << to << endl;
}
else{
func(n-1, from, other, to);
cout << "Move " << n-1 << "from " << from << " to " << to <<endl;
func(n-1, other, to, from);
}
}
void hanoi(int n){
if(n > 0){
func(n, "left", "right", "mid");
}
}
【打印全部子序列】
void process(string& s, int i){
if(i == s.size()){
for(int k = 0; k < s.size(); k++){
if(s[k] == '\0'){
continue;
}
cout << s[k];
}
cout << endl;
return;
}
process(s, i + 1);
char temp = s[i];
s[i] = '\0';
process(s, i + 1);
s[i] = temp;
}
void printAllSubsquence(string s){
process(s, 0);
}
【全排列】
void swap(string& s, int i, int j){
char temp = s[i];
s[i] = s[j];
s[j] = temp;
}
void process(string& s, int i, vector<string>& res){
if(i == s.size()){
res.push_back(s);
return;
}
//vector<int> visit(26, 0);
for(int j = i; j < s.size(); j++){
//if(visit[s[j] - 'a'] == 0){
// visit[s[j] - 'a'] = 1;
swap(s, i, j);
process(s, i + 1, res);
swap(s, i, j);
//}
}
}
vector<string> printAllSequence(string s){
vector<string> res;
process(s, 0, res);
return res;
}
全排列去重:启用注释掉的代码
【题目】
给定一个整形数组arr,代表数值不同的纸牌排成一条线。玩家A和玩家B依次拿走每张纸牌,规定玩家A先拿,玩家B后拿,但是每个玩家每次只能拿走最左或最右的纸牌,玩家A和玩家B都绝顶聪明。返回最后获胜者的分数。
【举例】
arr = [1, 2, 100, 4]
开始时,玩家A只能拿走1或4.如果开始时玩家A拿走1,则排列变为[2, 100, 4],接下来玩家B可以拿走2或4,然后继续轮到玩家A
如果开始时玩家A拿走4,则排列变为[1, 2, 100],接下来玩家B可以拿走1或100,然后继续轮到玩家A
玩家A作为绝顶聪明的人不会先拿4,因为拿4之后,玩家B将拿走100.所以玩家A会先拿1,让排列变为[2, 100, 4],接下来玩家B不管怎么选,100都会被玩家A拿走,玩家A会获胜,分数为101,所以返回101。
int max(int a, int b){
return a > b ? a : b;
}
int s(vector<int>& arr, int l, int j);
int f(vector<int>& arr, int l, int r){
if(l == r){
return arr[l];
}
else{
return max(arr[l] + s(arr, l + 1, r), arr[r] + s(arr, l, r - 1));
}
}
int s(vector<int>& arr, int l, int r){
if(l == r){
return 0;
}
else{
return min(f(arr, l + 1, r), f(arr, l, r - 1));
}
}
int cardsInLine(vector<int> arr){
if(arr.empty()){
return 0;
}
return max(f(arr, 0, arr.size() - 1), s(arr, 0, arr.size() - 1));
}
【逆序栈】
给你一个栈,请你逆序这歌栈,不能申请额外的数据结构,只能使用递归函数。如何实现?
// 返回栈底元素
int f(stack<int> stack){
int result = stack.top(); stack.pop();
if(stack.empty()){
return result;
}
else{
int last = f(stack);
stack.push(result);
return last;
}
}
void reverseStackUsingRecursive(stack<int> stack){
if(stack.empty()){
return;
}
int i = f(stack);
reverseStackUsingRecursive(stack);
stack.push(i);
}
【题目】
规定1和A对应,2和B对应,3和C对应...
那么一个数字字符串比如"111"们就可以转化为"AAA","KA","AK"。
给定一个只有数字字符组成的字符串str,返回有多少种转化结果。
int process(string& arr , int i){
if(i == arr.size()){
return 1;
}
if(arr[i] == '0'){
return 0;
}
if(arr[i] == '2'){
int res = process(arr, i + 1);
if(i + 1 < arr.size()){
res += process(arr, i + 2);
}
return res;
}
if(arr[i] == '1'){
int res = process(arr, i + 1);
if(i + 1 < arr.size() && arr[i + 1] >= '0' && arr[i + 1] <= '6'){
res += process(arr, i + 2);
}
return res;
}
return process(arr, i + 1);
}
【背包问题】
给定两个长度都为N的数组weights和values,weights[i]和values[i]分别代表i号物品的重量和价值。给定一个整数bag,表示一个载重bag的袋子,你装的物品不能超过这个重量。返回你能装下最多的价值。
int max(int a, int b){
return a > b ? a : b;
}
int process(vector<int>& weights, vector<int>& values, int i, int alreadyweight, int alreadyvalue, int bag){
if(alreadyweight > bag){
return 0;
}
if(i == weights.size()){
return alreadyvalue;
}
return max(process(weights, values, i + 1, alreadyweight, alreadyvalue, bag), process(weights, values, i + 1, alreadyweight + weights[i], alreadyvalue + values[i], bag));
}
int maxValue(vector<int>& weights, vector<int>& values, int bag){
return process(weights, values, 0, 0, 0, bag);
}