Verify Preorder Serialization of a Binary Tree

1.  解析

题目大意,给定一个','分割开的字符串,判断是否是先序遍历。树的3种遍历递归都比较简单,然而这题反其道而行之,未必就会啦~~~

2. 分析

我想到的一种解法就是,采用非递归方式的先序遍历,将解析字符串的过程看做是先序遍历的过程,不断将左节点进栈,即不停地从前往后解析字符串,每个','分割开的字符串就是一个节点,'#'代表空节点,直到碰到空节点。然后回溯,返回栈顶节点,即根节点,然后检索右边节点,...依次检索,如果是先序遍历,那整个过程就会一直执行到底;反之,如果栈中还有元素,可是字符串已经解析到尾部,说明不属于先序遍历。例如"2,3,4,#",左节点全部进栈,可是当回溯在根节点'4'的时候,整个字符串已经解析完,很明显,其他空节点还没有放上去,即不满足先序遍历.结果虽然AC,但是效率很低

class Solution {
public:
    bool isValidSerialization(string preorder) {
        preorder += ',';
        stack<string> nums{{""}};
        int pos;
        while(!nums.empty()){
            string str = nums.top();
            nums.pop();
            if (str != "#"){ //右边节点不为空
                pos = preorder.find(',');
                if (pos == string::npos) return false;
                while (pos != string::npos){ //左节点进栈
                    str = preorder.substr(0, pos);
                    preorder = preorder.substr(pos+1);
                    if (str == "#") break;
                    nums.push(str);
                    pos = preorder.find(',');
                }
            }          
        }
        return preorder.empty() ? true : false;
    }
};

3. 别的解法 

@Grandyang大家可以时常查看他的博客,很多题都讲解的很到位,我就经常光顾,不会就学嘛,多参考别人优秀的思想~~~哈哈。如果我们仔细观察就会发现:

①如果不考虑最后一个节点,是不会出现3个'#'紧挨在一块的情况,例如"3,#,#,#,3,#",如果出现这种情况一定不是先序遍历。

②不考虑最后一个'#',如果满足先序遍历,那么'#''数字'出现的次数一定是相等的,且总是先出现'数字'然后才出现'#'

综上两种情况,我们可以设置cnt表示'数字'出现的个数,如果cnt为0,且nums还未遍历完,那么意味着'数字'出现的次数小于'#',即不满足先序遍历,直接返回false。因为我们之前是不考虑最后一个'#'的,所以在最后我们要判断一下

class Solution {
public:
    bool isValidSerialization(string preorder){
        istringstream in(preorder);
        vector<string> nums;
        string str = "";
        int cnt = 0;
        while (getline(in, str, ',')) nums.push_back(str); //根据','解析节点值,放在数组当中
        for (int i = 0; i < nums.size() - 1; ++i){
            if (nums[i] == "#"){
                if (cnt == 0) return false;
                cnt--;
            } else{
                cnt++;
            }
        }
        return cnt == 0 && nums.back() == "#";
    }
};

这种解法实际上和上一种解法大同小异,整个字符串由','和0-9的字符与'#'组成,故可以以','作为分隔字符的标记,capacity代表'#'的容量,每增加一个节点就会增加两个空节点(即'#').

class Solution {
public:
    bool isValidSerialization(string preorder){
        preorder += ',';
        int capacity = 1;
        for (int i = 0; i < preorder.length(); ++i){
            if (preorder[i] != ',') continue;
            if (--capacity < 0) return false;
            if (preorder[i-1] != '#') capacity += 2;
        }
        return capacity == 0;
    }
};

 [1]https://www.cnblogs.com/grandyang/p/5174738.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值