剑指 Offer 46. 把数字翻译成字符串

title: 给定一个数字,我们按照如下规则把它翻译为字符串:0 翻译成 “a” ,1 翻译成 “b”,……,11 翻译成 “l”,……,25 翻译成 “z”。一个数字可能有多个翻译。请编程实现一个函数,用来计算一个数字有多少种不同的翻译方法。

输入: 12258
输出: 5
解释: 12258有5种不同的翻译,分别是"bccfi", "bwfi", "bczi", "mcfi"和"mzi"

一开始拿到题目,并没有太多的思路,只是觉得这是一个组合问题,一般组合问题,都可以用树形结构来表达。题目中存在某些隐形的条件:

  1. 被翻译的数字至多2位且不能超过25
  2. 被翻译的数字,不能有前导0
    因为条件1的存在,就决定了每次翻译,只有2种选择:只翻译一个或者2个,那么可以尝试着去画一下组合树
    用‘-’表示两个不同的部分,dash前是可以且已经被翻译,dash后是留着切分的,红色的点表示不能再往下切分了
    拿到一个字符串后,有2种翻译方式组合:
  • 只翻译一个数字
  • 翻译2个数字
    那么构建出来的树就是二叉树,我们每次翻译完本阶段后,接着切分并翻译剩下的字符串
    红色的节点代表不能再被切分但可以被翻译,不能再切分是因为
  • 前一步已经切分过,避免造成重复
  • 已经满足了最小的翻译条件

那么这很明显属于DFS,递归好像不太好处理,就可以用栈来实现

class Solution {
public:

	bool is_valid(string str){
		if(str[0]=='0') //前导0不行
			return false;
		int str2int = atoi(str.c_str());

		return str2int<=25;
	}

    int translateNum(int num) {
    	int count = 0;
        string str_num = to_string(num);
        int full_str_len = str_num.length();

        stack<string> s;
        s.push(str_num);

        string tmp_str,first_str,sencond_str,rest_firstr_str,rest_second_str;

        while(!s.empty()){
        	string top_str = s.top();

        	if(top_str.length()==1){
        		count++;
        		s.pop();
        		continue;
        	}

			if(top_str.length()==2 && is_valid(top_str))
        		count++;//2位数且小于26,那么可以接受,也是一种情况

        	s.pop();
        	
        	first_str = top_str.substr(0,1);
        	rest_firstr_str = top_str.substr(1,full_str_len);
                  
                  //小于等于2位数的时候,就不用再继续切分了,因为上面已经切分
        	if(top_str.length()>2){
        		sencond_str = top_str.substr(0,2);
        		rest_second_str = top_str.substr(2,full_str_len);

        		if(is_valid(sencond_str))
        			s.push(rest_second_str);
        	}

        	s.push(rest_firstr_str);
        }

        return count;

    }
};

posted @ 2020-06-26 16:27  real-zhouyc  阅读(139)  评论(0编辑  收藏  举报