算法整理-二叉树和堆栈

1.   二叉树:

     (1) 最大深度: 递归, 最大深度等于左子树最大深度和右子树最大深度之间的最大值 + 1。

     (2) 最小深度: 递归,当左右子树均不为空时,最小深度等于左子树和右子树的最小深度之间的最小值 +1, 当有一边子树为空时,最小深度等于左子树最小深度和右子树最小深度之间的最大值+1.       

     (3)Symmetric Tree:  判断树是否是镜像树:

            递归的判断两棵树是否镜像,条件: 根节点的值相同,A的左子树和B的右子树镜像,A的右子树和B的左子树镜像。

class Solution {
public:
    bool isSymmetric(TreeNode* root) {
     if (root == NULL) return true;
     return checkSymmetric(root->left, root->right);
    }
private:
    bool checkSymmetric(TreeNode* p1, TreeNode *p2) {
        if (p1 == NULL && p2 == NULL) return true;
        if (p1 == NULL || p2 == NULL) return false;
        if (p1->val == p2->val) {
            return checkSymmetric(p1->left, p2->right) && checkSymmetric(p1->right, p2->left);

        }
        return false;
    }

      (4) 从先序和中序数组构造二叉树:

             先序数组第一个元素为根, 找到中序数组中的根,分为左子树和右子树进行递归。            

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        int ps = 0;
        int pe = preorder.size() - 1;
        int is = 0;
        int ie = inorder.size() - 1;
        return construct(preorder, inorder, ps, pe, is, ie);
        
    }
private:
    TreeNode* construct(vector<int>& preorder, vector<int> inorder, int ps, int pe, int is ,int ie){
        if (ps > pe) {
            return nullptr;
        }
        TreeNode* root = new TreeNode(preorder[ps]);
        int pos;
        for (int i =is; i <=ie; i++) {
            if (inorder[i] == root->val){
                 pos = i;
                 break;
            }
        }
        root->left = construct(preorder, inorder, ps + 1, ps + pos - is, is, pos - 1);
        root->right = construct(preorder, inorder, ps + pos -is + 1, pe, pos+1, ie);
        return root;
    }
};

      (5)有序数组构造搜索二叉树

   BST的根是数组的中位数结点。先构建根结点,再递归构造左子树和右子树。 如果改成有序链表构造二叉树,每次找到中间的结点是O(N)的, 用快慢指针,一个走一步,一个走两步。       

class Solution {
public:
    TreeNode* sortedArrayToBST(vector<int>& nums) {
        int len = nums.size();
        if (len == 0) return NULL;
        return constructTree(nums, 0, len-1);
    }
private:
   TreeNode* constructTree(const vector<int> &nums, int s, int e) {
       if (s > e )  return NULL;
       int mid = (s + e) / 2;
       TreeNode* root = new TreeNode(nums[mid]);
       root->left = constructTree(nums, s, mid - 1);
       root->right = constructTree(nums, mid + 1, e);
       return root;
   }
};

    升级后的有序链表, 用一个全局listnode指针, 有序链表是中序遍历二叉树的结果,进行中序二叉树建立。

class Solution {
public:
    TreeNode* sortedListToBST(ListNode* head) {
        if (head == NULL) return NULL;
        ListNode *p = head;
        int n = 0;
        while(p->next !=NULL) {
             p = p->next;
             n++;
        }
        node = head;
        return constructMidTree(head, 0, n);
    }

private:
    ListNode* node;
    TreeNode* constructMidTree(ListNode* head, int s, int e){
        if (s > e ) return NULL;
        int mid = (s + e) / 2;
        TreeNode* left = constructMidTree(head, s, mid-1);
        TreeNode* root = new TreeNode(node->val);
        node = node->next;
        root->left = left;
        root->right = constructMidTree(head, mid+1, e);
        return root;
    }
};

 

2.  堆栈

 (1) 解码字符串 

  举例:s = "3[a]2[bc]", return "aaabcbc", s = "3[a2[c]]", return "accaccacc", s = "2[abc]3[cd]ef", return "abcabccdcdcdef".

     采用一个stack<vector<int>>  s1 维护出现的次数,采用一个stack<vector<string>>  s2维护当前层次解码后的string, 妻子一个[]代表一个层次。遇到的字符分为三种情况,数字则s1入栈(连续的数字字符是一个数字),[则新建层次入s2, 字符则append到栈顶str, ]则解码一次减少一个层次,s1.pop().  s2.pop(), 扩展后更新s2.top().

   

    string decodeString(string s) {
        int len = s.size();
        if (len == 0) return s;
        int i = 0;
        stack<int> helper_count;
        stack<string> helper_string;
        helper_string.push("");
        while (i < len) {
            if (s[i] >= '1' && s[i] <= '9') {
                 int count = 0;
                 while(s[i] !='[') {
                     count = 10 * count + int(s[i] - '0');
                     i++;
                 }              
                 helper_count.push(count);
                 helper_string.push("");
                 i++;
            }
            else if ((s[i] >= 'a' && s[i] <= 'z') ||(s[i] >= 'A' && s[i] <= 'Z'))  {
                string top = helper_string.top();
                helper_string.pop();
                helper_string.push(top + s[i]);
                i++;
            }
           else {
               int top_count = helper_count.top();
               helper_count.pop();
               string top_str = helper_string.top();
               helper_string.pop();
               string upt_str;
               for (int c=0; c<top_count; c++) {
                   upt_str += top_str;
               }
               upt_str  = helper_string.top() + upt_str;
               helper_string.pop();
               helper_string.push(upt_str);
               i++;
           }     
        }
        return helper_string.top();
    }

 

(2)  计算式的后序表达

           3

         /     \       

       +      *

     /    \

     2    1      

Example 1:

Input: ["2", "1", "+", "3", "*"]
Output: 9
Explanation: ((2 + 1) * 3) = 9

  用一个stack<int> 维护数字,遇见数字则进栈, 遇见符号则从栈顶出来两个元素,计算(top2 * top1),计算结果入栈。

  复习: C++ 函数: 字符串数字 转数字:   atoi(string.c_str())

//string转char*:
 string str=“world”;
const char *p = str.c_str();
//char* 转string
string s;
char *p = "hello";//直接赋值
s = p;

 

   

public:
    int evalRPN(vector<string>& tokens) {
       int len = tokens.size();
       stack<int> helper;
       for (int i = 0; i < len; i++) {
           if (!isSymbol(tokens[i])) {
               helper.push(atoi(tokens[i].c_str()));
           }
           else {
               int top1 = helper.top();
               helper.pop();
               int top2 = helper.top();
               helper.pop();
               int new_top = compute(top2, top1, tokens[i]);
               helper.push(new_top);
           }
       }
       return helper.top();

    }
private:
     int compute(int x, int y, string symbol) {

             if (symbol == "+") 
               return x + y;
             else if (symbol == "-")
               return x - y;
             else if (symbol == "*")
               return x * y;
             else
               return x / y; 
     }

     bool isSymbol(string a) {
         if (a == "+" || a == "-" || a== "*" || a == "/"){
             return true;
         }
         return false;
     }

 

(3) 统计化学元素

Input: 
formula = "Mg(OH)2"
Output: "H2MgO2"
Explanation: 
The count of elements are {'H': 2, 'Mg': 1, 'O': 2}.
用一个栈维护数字,一个栈维护 stack<map<string,int>>, 遍历时分为一下几种情况,字符,则判断后续有没有数字,更新栈顶元素,左括号则新建层次,右括号则减去一个层次。
class Solution {
public:
    string countOfAtoms(string formula) {
        int len = formula.size();
        stack<map<string, int>> helper;
        map<string, int> init;
        helper.push(init);
        int i = 0;
        while (i < len) {
            if (formula[i] >= 'A' && formula[i] <= 'Z'){
                string cur = "";
                cur =  formula[i++];
                cout << cur;
                while(i < len && formula[i] >= 'a'&& formula[i] <= 'z'){
                    cur += formula[i++];
                }
                int count = 1;
                if (i < len && isnumber(formula[i])) {
                    count = 0;
                    while(i< len && isnumber(formula[i])){
                        count = count * 10 + (formula[i] - '0');
                        i++;
                    }
                }
   
             // update map top element
               updateTop(helper, make_pair(cur, count));
             }
            else if (formula[i] == '(') {
                map<string, int> temp;
                helper.push(temp);
                i++;
            }
            else if (formula[i] == ')') {
                 i++;
                 int count = 1;
                 if (i < len && isnumber(formula[i])) {
                    count = 0; 
                    while(i < len && isnumber(formula[i])){
                        count = count * 10 + (formula[i] - '0');
                        i++;
                    }
                }
                mergeTop(helper, count);
                // merge top1 * count + top2 to the new top
            }
        }
        map<string, int>::iterator iter;
        map<string, int> final = helper.top();
        string result="";
        for (iter = final.begin(); iter != final.end(); iter++){               
            result += iter->first;
            if (iter->second > 1)
              result += to_string(iter->second);        
        }

        return result;
    }

private:
    bool isnumber(char s) {
        if (s >= '0' && s <= '9') return true;
        return false;
    }
    void updateTop(stack<map<string, int>> &helper, const pair<string, int>p) {
          map<string, int> &top_map = helper.top();
          //map<string, int>::iterator iter = top_map.find(p.first);
          top_map[p.first] += p.second;
         return;
    }
    void mergeTop(stack<map<string, int>>& helper, const int count) {
        map<string, int> top1_map = helper.top();
        helper.pop();
        map<string, int> &top2_map = helper.top();
        map<string, int>::iterator iter;
        for (iter = top1_map.begin(); iter != top1_map.end(); iter++) {
            //map<string, int>::iterator iter_find = top2_map.find(iter->first);
            top2_map[iter->first] += iter->second * count;
        }
       return;


    }

};

 

 

复习map:

map<string, int> myMap;
map<string, int> :: iterator iter;
string test

// 查找key是否存在:iter =  a.find(test); if (iter == myMap.end());

//新加key: 

    myMap[test] = 0;  //若不存在则自动初始化为0。
    mapStudent.insert(pair<string, string>("r000", "student_zero"));

//迭代器刪除
iter = mapStudent.find("r123");
mapStudent.erase(iter);
 
//用關鍵字刪除
int n = mapStudent.erase("r123");//如果刪除了會返回1,否則返回0
 
//用迭代器範圍刪除 : 把整個map清空
mapStudent.erase(mapStudent.begin(), mapStudent.end());
//等同於mapStudent.clear()

 

 

        

posted @ 2019-06-24 22:53  cookcoder  阅读(726)  评论(0编辑  收藏  举报