美文网首页
Day3 字符串排列⭐+重建二叉树⭐+顺时针打印矩阵

Day3 字符串排列⭐+重建二叉树⭐+顺时针打印矩阵

作者: 吃掉夏天的怪物 | 来源:发表于2021-06-10 15:03 被阅读0次

    剑指 Offer 38. 字符串的排列(中等)

    还需要再做做。注意这里用了一个set是为了处理有相同字母的情况的。
    比如,aab,如果不用set,那aab,第一个a放在第一位和aab,第二个a放在第一位,就会是两个结果。

    class Solution {
    public:
      vector<string> permutation(string s) {
          dfs(s,0);
          return res;
    
      }
    private:
      vector<string> res;
      void dfs(string s, int x){
          if(x == s.size()-1){
              res.push_back(s);
              return ;
          }
          set<char> hi;
          for(int i = x; i< s.size();i++){
              if(hi.count(s[i])){continue;}
              hi.insert(s[i]);
              swap(s[i],s[x]);
              dfs(s,x+1);
              swap(s[i],s[x]);
          }
    
      }
    
    };
    

    剑指 Offer 07. 重建二叉树

    不大会,还需要再做做

    1. 递归

    这个方法比较简单,可以先建立个中序遍历的hash表,方便找到前序遍历每个节点在中序中的对应位置。递归的中止条件就是前序遍历递归结束。对于前序遍历,我们可以找到中序遍历数组中,[left,root] [root,right]结点的范围。

    class Solution {
    private:
        unordered_map<int,int> ids;
    public:
        TreeNode* tree(vector<int>& preorder, vector<int>&inorder, int preleft, int preright, int inleft, int inright){
            if(preleft > preright) return nullptr;
    
            int root_val = preorder[preleft];//in中顺序
            TreeNode* t = new TreeNode(root_val);
            
            int size_tree = ids[root_val] - inleft;
            t->left = tree(preorder, inorder, preleft+1, preleft+size_tree,inleft,ids[root_val]-1);
            t->right = tree(preorder,inorder,preleft+size_tree+1,preright,ids[root_val]+1,inright);
            return t;
    
        }
        TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
            
            int i =0;
            for(auto it:inorder){
                ids[it] = i++;
            }
            return tree(preorder,inorder,0,preorder.size()-1,0,preorder.size()-1);
    
        }
    };
    

    2. 迭代

    这个方法,模拟了好一会。似懂非懂,但是好巧妙哦。
    前序: 左 中 右
    中序: 中 左 右
    对于前序而言:
    [...,a,b,c,d,...]
    b 只有两种可能,①a的左孩子,②a或者a父节点的右孩子
    如何确定b是左孩子还是右孩子呢,遍历前序的时候,构建树。(对照着中序值不一样,相当于都是左边的),当遇到中序和前序某结点一样时说明来了个右孩子。出栈对比,前序出栈的顺序就是....

    what.jpg
    class Solution {
    public:
        TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
            if(preorder.size() <= 0) return nullptr;
            TreeNode* node = new TreeNode(preorder[0]);
            stack<TreeNode*> s;
            s.push(node);
            int in_index = 0;
    
            for(int i =1; i<preorder.size(); i++){
                TreeNode* root = s.top();
                int preval = preorder[i];
                if(root->val != inorder[in_index]){
                    root->left = new TreeNode(preval);
                    s.push(root->left);
                }else{
                    while(!s.empty() && s.top()->val == inorder[in_index]){
                        root = s.top();
                        s.pop();
                        in_index++;
                    }
                    root->right = new TreeNode(preval);
                    s.push(root->right);
                }
            }
            return node;
        }
    };
    

    剑指 Offer 29. 顺时针打印矩阵(简单)

    简单题,但是为什么才击败7%呢。其实没有必要用if判断,只要有一个不符合就不用继续下去了。

    class Solution {
    public:
      vector<int> spiralOrder(vector<vector<int>>& matrix) {
          int n = matrix.size();
          if(n == 0) return {};
          int m = matrix[0].size();
          if(m == 0) return {};
          int count = n*m;
          
          int left =0, right =m-1, top = 0, bottom = n-1;
          vector<int> res(count);
          int i = 0;
          while(i< count){
              //从左向右
              if(top <= bottom){ //❗可以改变成,再top = top+1后判断if(top>right) 则break
              for(int k = left; k <= right; k++){
                  res[i++] = matrix[top][k];
              }
              top = top +1;}
              //从上向下
              if(right>=left){
              for(int k = top; k<=bottom; k++){
                  res[i++] = matrix[k][right];
              }
              right = right-1;}
    
             //从右向左
             if(bottom>=top){
              for(int k = right; k >= left; k--){
                  res[i++] = matrix[bottom][k];
              }
              bottom = bottom-1;}
             //从下向上
             if(left<=right){
              for(int k = bottom; k >= top; k--){
                  res[i++] = matrix[k][left];
              }
              left++;
             }
          }
          return res;
      }
    };
    

    改动了一点,击败67%

    class Solution {
    public:
        vector<int> spiralOrder(vector<vector<int>>& matrix) {
            int n = matrix.size();
            if(n == 0) return {};
            int m = matrix[0].size();
            if(m == 0) return {};
            
            int left =0, right =m-1, top = 0, bottom = n-1;
            vector<int> res;
            while(true){
                //从左向右
                for(int k = left; k <= right; k++){
                    res.push_back(matrix[top][k]);
                }
                top = top +1;
                if(top > bottom) break;
                //从上向下
               
                for(int k = top; k<=bottom; k++){
                    res.push_back(matrix[k][right]);
                }
                right = right-1;
                if(right < left) break;
               //从右向左
               
                for(int k = right; k >= left; k--){
                    res.push_back(matrix[bottom][k]);
                }
                bottom = bottom-1;
                if(bottom < top) break;
               //从下向上
              
                for(int k = bottom; k >= top; k--){
                    res.push_back(matrix[k][left]);
                }
                left++;
               if(left > right)break;
            }
            return res;
        }
    };
    

    相关文章

      网友评论

          本文标题:Day3 字符串排列⭐+重建二叉树⭐+顺时针打印矩阵

          本文链接:https://www.haomeiwen.com/subject/hgnyeltx.html