剑指 Offer II 树

我为什么要把代码粘在这里

断更很久了,基于一个错误的观念:我想看题,我到leetcode官网看不就行了吗?
但是若干年后我可能还会到我的博客园看看呀,我有可能上刷题网站吗?而且心得不好写到注释上。
记博客是长久的事,不能贪一时的方便。

这两周我并不是没有记博客,大致看完了图解系统 看了图解网络的tcp 看了10篇mysql45讲 截原图太多了 不好意思发
还有做项目 也是就自己看看。

---2022.3.23

047. 二叉树剪枝

class Solution {
    public TreeNode pruneTree(TreeNode root) {  
        if( root.left!=null) root.left= pruneTree(root.left);
        if(root.right!=null)root.right= pruneTree(root.right);
        if(root.val==0&&root.left==null&&root.right==null)root=null;
        return root;

    }
}

很难048. 序列化与反序列化二叉树

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Codec {

    // Encodes a tree to a single string.

    StringBuffer s=new StringBuffer("");
    public String serialize(TreeNode root) {
        dfs(root);
       
        return s.toString();
        
    }
    void dfs(TreeNode  root)
    {
        if(root==null) 
        {
             s.append("null,");
           
        } 
        else
        {
        s.append( String.valueOf(root.val)+",");
        dfs(root.left);
        dfs(root.right);
        }

    }


    String [] data_array;
     List<String> list;
    public TreeNode deserialize(String data) {
        data_array=data.split(",");  
         
        list=new LinkedList<String>(Arrays.asList(data_array));
       // for (String x:list)System.out.println(x);
        return tdfs();
        
    }
    TreeNode tdfs()
    {
        
        if(list.get(0).equals("null"))
        {
            list.remove(0);
            return null;
        }
        TreeNode root=new TreeNode(Integer.valueOf(list.get(0)));
         list.remove(0);
        root.left=tdfs();
        root.right=tdfs();
        return root;
    }
}

// Your Codec object will be instantiated and called as such:
// Codec ser = new Codec();
// Codec deser = new Codec();
// TreeNode ans = deser.deserialize(ser.serialize(root));

049. 从根节点到叶节点的路径数字之和

class Solution {
    int ans=0;
    int dfs(int sum,TreeNode root)//sum是之前节点值
    {
        TreeNode p=root.left,q=root.right;
        if(p==null&&q==null)return sum*10+root.val;
        int res=0;
        if(p!=null)res+= dfs(root.val+sum*10,p);
        if(q!=null)res+= dfs(root.val+sum*10,q);
        return res;
    }
    public int sumNumbers(TreeNode root) {
        return dfs(0,root);
    }
}

050. 向下的路径节点之和

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    int ans=0;
    void dfs(TreeNode root,int targetSum)
    {
        if(root==null)
        {
            return ;
        }
        if(root.val==targetSum) {
            ans++;
        }
           
       dfs(root.left,targetSum-root.val);
      dfs(root.right,targetSum-root.val);
    }
    public int pathSum(TreeNode root, int targetSum) {
        if(root==null)return 0;
     
       dfs(root,targetSum);
pathSum(root.left,targetSum);
pathSum(root.right,targetSum);
        return ans;

    }
}

做法秀爆了051. 节点之和最大的路径

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    int ans;
    public int maxPathSum(TreeNode root) {
        ans=Integer.MIN_VALUE;
       dfs(root);
        return ans;
    }
    int dfs(TreeNode root)//秀在int 维护路径最大值
    {
        if(root==null)return 0;
        int lmax=Math.max(0,dfs(root.left));//小于0还不如不加
        int rmax=Math.max(0,dfs(root.right));
        ans=Math.max(lmax+rmax+root.val,ans);
        return root.val+Math.max(lmax,rmax);//这里维护一条最长的路径太秀了
    }
}

052. 展平二叉搜索树

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    TreeNode tail;
    void dfs(TreeNode root)
    {
        if(root==null)return ;

        dfs(root.left);
        root.left=null;
         tail.right= root;
         tail=tail.right;
        dfs(root.right);
    }
    public TreeNode increasingBST(TreeNode root) {
          TreeNode dummy=new TreeNode(-1);
          tail=dummy;
          dfs(root);
          return dummy.right;


    }
}

053. 二叉搜索树中的中序后继

class Solution {
public:
    int flag=0;//状态0没找到p 1找到p没找到比p->val大的 2找到了 全部return 
    TreeNode* ans=new TreeNode();
    void dfs(TreeNode* root, TreeNode* p)
    {
        if(flag==2)return ;
        if(!root)return ;
        dfs(root->left,p);
        if(p==root)flag=1;
        if(flag==1&&root->val>p->val)
        {
            flag=2;
            ans->right=root;
            return ;
        }
        dfs(root->right,p);

    }
    TreeNode* inorderSuccessor(TreeNode* root, TreeNode* p) {
         dfs(root,p);
         return ans->right;

        
    }
};

054. 所有大于等于节点的值之和


class Solution {
public:
    vector<int>a,b;

    void dfs(TreeNode* root)
    {
        if(!root)return ;
        if(root)a.push_back(root->val);
         dfs(root->left);
         dfs(root->right);

    }
/*
二分找到 第一个a里面比root->val大的值 ,把root->val替换为 后缀和 注意是后缀和
*/
     void change(TreeNode* root)
     {
         if(!root)return ;
         int x=root->val;
         int l=0,r=a.size()-1;
         while(l<r) 
         {
             int mid=l+r>>1;
             if(a[mid]>=x)r=mid;
             else l=mid+1;
         }
         root->val=b[l];
         change(root->left);
         change(root->right);
     }
    TreeNode* convertBST(TreeNode* root) {
        dfs(root);
        sort(a.begin(),a.end());
        for(int x:a)b.push_back(x);
        int n=b.size();
        for(int i=n-2;i>=0;i--)b[i]+=b[i+1];
        change(root);
        return root;
    }
};

055. 二叉搜索树迭代器

class BSTIterator {
public:
    TreeNode* dummy=new TreeNode(-1);
     TreeNode* p=dummy;
    void dfs(TreeNode* root)
    {
        if(!root)return ;
        dfs(root->left);
        dummy->right=root;
        dummy=dummy->right;//可以合成一步 但没必要
        //这里相当于把它拉成一个往右的链表
        dfs(root->right);
    }
    BSTIterator(TreeNode* root) {
       dfs(root);

    }
    
    int next() {
       p=p->right;
        return p->val;


    }
    
    bool hasNext() {
        return p->right;

    }
};

056. 二叉搜索树中两个节点之和

哈希表 ez


class Solution {
public:
bool flag=false;
    unordered_map<int ,int >memo;
    void dfs(TreeNode* root,int k)
    {
        if(flag)return ;

        if(!root)return ;
        if(memo.find(k-root->val)!=memo.end())
        {
            flag=true;
        }
        memo[root->val]++;
        dfs(root->left,k);
        dfs(root->right,k);
    }
    bool findTarget(TreeNode* root, int k) {
         dfs(root,k);

         return flag;
    }
};

057. 值和下标之差都在给定的范围内 典型题

1.找离给定数字最接近的值是多少(第一个大于等于 第一个小于) 用set+二分

2.set维护滑动窗口

    bool containsNearbyAlmostDuplicate(vector<int>& nums, int k, int t) {
        typedef long long LL;
        multiset<LL>S;
        S.insert(1e18),S.insert(-1e18);//哨兵 肯定会返回
        for(int i=0,j=0;i<nums.size();i++)
        {
            if(i-j>k)S.erase(S.find(nums[j++]));//find是因为只想删一个 所以用迭代器  不find全删了
            int x=nums[i];
            auto it= S.lower_bound(x);
            //大于等于x最小的数
            if(*it-x<=t)return true;
            it--;
            //小于x的最大数
            if(x-*it<=t)return true;
            S.insert(x);
     /*
     set不包含重复元素 multiset可以
       insert 插入一个数
       find()q.find(1)!=q.end(); //查找元素是否在set 找不到就返回end迭代器
       count(x) 返回x的个数 set只可能0,1 multiset可能多个
       erase()
       1.输入一个数x  删除所有x O(k+logn)
       2.输入1个迭代器 删掉这个迭代器
       lower_bound()返回大于等于x的最小的数的迭代器 不存在返回end
       upper_bound()返回大于x的最小的数
       迭代器支持*解除引用 不支持随机访问 支持++ 和-- 复杂度logn 前驱是前一个数 后继是后一个数
     */
        }
        return false;
    }

058. 日程表 set+pair

找找离给点区间 最近的左右端点
i = lower_bound第一个右端点
i-- 左端点

class MyCalendar {
public:
typedef pair<int,int>PII;
int INF=2e9;
set<PII>S;
    MyCalendar() {
        //不想判断边界
        S.insert({-INF,-INF});
        S.insert({INF,INF});


    }
    bool check(PII a,PII b)//左开右闭 是否有交集
    {
        if(a.second<=b.first)return false;
        if(b.second<=a.first)return false;
        return true;

    }
    //找离给点区间 最近的左右端点 
    bool book(int start, int end) {
        auto i=S.lower_bound({start,start});
        auto j=i;
        j--;
        PII t(start,end);
        if(check(*i,t)||check(*j,t))return false;
        S.insert(t);
        return true;
    }
};
posted @ 2022-03-09 17:57  liv_vil  阅读(30)  评论(0)    收藏  举报