牛客网初级算法之七(暴力递归和动态规划)

题目一:汉诺塔问题

汉诺塔问题是一个经典的问题。汉诺塔(Hanoi Tower),又称河内塔,源于印度一个古老传说。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,任何时候,在小圆盘上都不能放大圆盘,且在三根柱子之间一次只能移动一个圆盘。问应该如何操作?

思路:

可以把问题理解为 把 1-n个数从一个位置移动到另一个位置,移动后的数字顺序不变

左边 -> 右边   辅助

1           1

|            |

n          n

代码和注释如下:

/*
 可以理解为 1-n个数 从 from 移动到to上去,可以借助help,规律就是
 首先把1- n-1 个数 从 from 移动到 help,借助to
 然后把最后一个圆盘 从 from移动到to
 最后把1-n-1个数从help 移动到to,借助from
 参数1:目前为1-n个圆盘
 参数2: 圆盘的初始位置
 参数3: 圆盘的目标位置
 参数4: 辅助位置
 */
void process(int N,string from,string to ,string help){
    if(N==1){//最后剩下一个盘
        printf("%s\n",("move 1 from "+from + " to "+to).c_str());
    }
    else {
        process(N-1, from, help, to);
        printf("%s\n",("move "+to_string(N)+" from "+from + " to "+to).c_str());
        process(N-1, help, to, from);
    }
}

题目二:

打印字符串的子序列

如 abc 的所有子序列为:

abc
ab
ac
a
bc
b
c

[]

思路:

可以利用递归回溯的思路,每一个字符在排列中都可以存在或者不存在,如果有n个数,那么就有2的n次方种排列,如下代码

void printZZZSub(string &s,int i,string& result){
    if(i==s.length()){
        printf("%s\n",result.c_str());
        return;
    }
    result+=s[i];//要当前字符
    printZZZSub(s, i+1,result);
    //不要当前字符
    result.erase(result.end() - 1);
    printZZZSub(s, i+1,result);

}
void printZZZ(string s){
    string res="";
    printZZZSub(s, 0, res);
}

题目三:打印字符串的全排列

如 abc的全排列为:

abc
acb
bac
bca
cba
cab

猜你喜欢

转载自www.cnblogs.com/xiaonanxia/p/10779400.html