Leetcode hot 100(day 4)

打印 上一主题 下一主题

主题 1688|帖子 1688|积分 5064

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
翻转二叉树
做法:递归即可,留意判断为空
  1. class Solution {
  2. public:
  3.     TreeNode* invertTree(TreeNode* root) {
  4.         if(root==nullptr)return nullptr;
  5.         TreeNode* node=root->left;
  6.         root->left=invertTree(root->right);
  7.         root->right=invertTree(node);
  8.         return root;
  9.     }
  10. };
复制代码

对称二叉树
做法一:递归。使用两个不同的指针进入递归即可
  1. class Solution {
  2. public:
  3.     bool check(TreeNode* p,TreeNode* q)
  4.     {
  5.         if(!p&&!q)return true;
  6.         if(!p||!q)return false;
  7.         return p->val==q->val&&check(p->left,q->right)&&check(p->right,q->left);
  8.     }
  9.     bool isSymmetric(TreeNode* root) {
  10.         return check(root->left,root->right);
  11.     }
  12. };
复制代码
做法二:迭代。一开始想用deque,但卡在了迭代怎么能让同一层进行比力,后面看了题解才知道可以直接用queue,只要压入的时间保证次序即可
  1. class Solution {
  2. public:
  3.     bool check(TreeNode* u, TreeNode* v) {
  4.         queue<TreeNode*> q;
  5.         q.push(u);
  6.         q.push(v);
  7.         while(!q.empty())
  8.         {
  9.             u=q.front();
  10.             q.pop();
  11.             v=q.front();
  12.             q.pop();
  13.             if(!u&&!v)continue;
  14.             if((!u||!v)||(u->val!=v->val))return false;
  15.             q.push(u->left);
  16.             q.push(v->right);
  17.             q.push(u->right);
  18.             q.push(v->left);
  19.         }
  20.         return true;
  21.     }
  22.     bool isSymmetric(TreeNode* root) {
  23.         return check(root->left,root->right);
  24.     }
  25. };
复制代码

二叉树的直径
做法:一开始想用树形dp,但发现搞复杂了根本不用。实在最直观的思想就是,对每个节点依次遍历,然后求左子树和右子树深度,然后进行比力。但我们可以发现,在这一过程中,重复搜刮了很多地方。要么影象化搜刮,要么就直接在递归中比力即可,如许就只必要递归一次。
  1. class Solution {
  2. public:
  3.     int ans=0;
  4.     int depth(TreeNode* root)
  5.     {
  6.         if(root==nullptr)return 0;
  7.         int L=depth(root->left);
  8.         int R=depth(root->right);
  9.         ans=max(ans,L+R+1);
  10.         return max(L,R)+1;
  11.     }
  12.     int diameterOfBinaryTree(TreeNode* root) {
  13.         depth(root);
  14.         return ans-1;
  15.     }
  16. };
复制代码

二叉树的层序遍历
做法一:迭代,BFS,记录一下每层的节点个数即可
  1. class Solution {
  2. public:
  3.     vector<vector<int>> levelOrder(TreeNode* root) {
  4.         if(root==nullptr)return {};
  5.         vector<vector<int>> vec;
  6.         queue<TreeNode*>q;
  7.         q.push(root);
  8.         while(!q.empty())
  9.         {
  10.             vector<int> v;
  11.             int sz=q.size();
  12.             for(int i=1;i<=sz;i++)
  13.             {
  14.                 auto u=q.front();
  15.                 q.pop();
  16.                 if(u->left!=nullptr)q.push(u->left);
  17.                 if(u->right!=nullptr)q.push(u->right);
  18.                 v.emplace_back(u->val);
  19.             }
  20.             vec.emplace_back(v);
  21.         }        
  22.         return vec;
  23.     }
  24. };
复制代码
做法二:递归,这个想法很精妙
  1. class Solution {
  2. private:
  3.     vector<vector<int>> ret;
  4. public:
  5.     vector<vector<int>> levelOrder(TreeNode* root) {
  6.         dfs(root,0);
  7.         return ret;
  8.     }
  9.     void dfs(TreeNode* root,int deep)
  10.     {
  11.         if(root == nullptr) return;
  12.         if(deep>=ret.size()) ret.push_back({root->val});
  13.         else ret[deep].push_back(root->val);
  14.         dfs(root->left,deep+1);
  15.         dfs(root->right,deep+1);
  16.     }
  17. };
复制代码

将有序数组转换为二叉搜刮树
做法:每次建立中间节点即可,然后递归建立树
  1. class Solution {
  2. public:
  3.     TreeNode* build(vector<int>& nums,int left,int right)
  4.     {
  5.         if(left>right)return nullptr;
  6.         int mid=(left+right)>>1;
  7.         TreeNode* root=new TreeNode(nums[mid]);
  8.         root->left=build(nums,left,mid-1);
  9.         root->right=build(nums,mid+1,right);
  10.         return root;
  11.     }
  12.     TreeNode* sortedArrayToBST(vector<int>& nums) {
  13.         return build(nums,0,nums.size()-1);
  14.     }
  15. };
复制代码

验证二叉搜刮树
做法一:分别dfs两边的子树,如果不满意条件就返回false
  1. class Solution {
  2. public:
  3.     bool dfs(TreeNode* root,long long lower,long long upper)
  4.     {
  5.         if(root==nullptr)return true;
  6.         if(root->val<=lower||root->val>=upper)return false;
  7.         return dfs(root->left,lower,root->val)&&dfs(root->right,root->val,upper);
  8.     }
  9.     bool isValidBST(TreeNode* root) {
  10.         return dfs(root,LONG_MIN,LONG_MAX);
  11.     }
  12. };
复制代码
做法二:中序遍历。这里可以递归大概不递归都可以
  1. class Solution {
  2. public:
  3.     vector<int> vec;
  4.     bool flag=true;
  5.     void dfs(TreeNode* root)
  6.     {
  7.         if(root==nullptr)return;
  8.         dfs(root->left);
  9.         if(vec.size()&&vec.back()>=root->val)
  10.         {
  11.             flag=false;
  12.             return;
  13.         }
  14.         vec.emplace_back(root->val);
  15.         dfs(root->right);
  16.     }
  17.     bool isValidBST(TreeNode* root) {
  18.         dfs(root);
  19.         return flag;
  20.     }
  21. };
复制代码

二叉搜刮树中第k小的元素
做法一:非优化。简单直接的中序遍历,刚好练一下非递归
  1. class Solution {
  2. public:
  3.     int kthSmallest(TreeNode* root, int k) {
  4.         int cnt=0;
  5.         stack<TreeNode*> s;
  6.         while(root!=nullptr||!s.empty())
  7.         {
  8.             if(root!=nullptr)
  9.             {
  10.                 s.push(root);
  11.                 root=root->left;
  12.             }
  13.             else
  14.             {
  15.                 root=s.top();
  16.                 s.pop();
  17.                 cnt++;
  18.                 if(cnt==k)return root->val;
  19.                 root=root->right;
  20.             }
  21.         }
  22.         return -1;
  23.     }
  24. };
复制代码
做法二:如果要频繁访问第k小的数字,可以通过预处理节点数,有点雷同快排找第k个大的
  1. class Solution {
  2. public:
  3.     unordered_map<TreeNode*,int>nodenum;
  4.     int countnodenum(TreeNode* node)
  5.     {
  6.         if(node==nullptr)return 0;
  7.         nodenum[node]=1+countnodenum(node->left)+countnodenum(node->right);
  8.         return nodenum[node];
  9.     }
  10.     int getnodenum(TreeNode* node)
  11.     {
  12.         if(node!=nullptr&&nodenum.count(node))
  13.         {
  14.             return nodenum[node];
  15.         }
  16.         return 0;
  17.     }
  18.    
  19.     int kthSmallest(TreeNode* root, int k) {
  20.         countnodenum(root);
  21.         while(root!=nullptr)
  22.         {
  23.             int left=getnodenum(root->left);
  24.             if(left<k-1)
  25.             {
  26.                 root=root->right;
  27.                 k-=left+1;
  28.             }
  29.             else if(left==k-1)break;
  30.             else root=root->left;
  31.         }   
  32.         return root->val;
  33.     }
  34. };
复制代码

二叉树的右视图
做法一:迭代,广度优先遍历即可
  1. class Solution {
  2. public:
  3.     vector<int> rightSideView(TreeNode* root) {
  4.         if(root==nullptr)return {};
  5.         queue<TreeNode*> q;
  6.         vector<int> vec;
  7.         q.push(root);
  8.         while(!q.empty())
  9.         {
  10.             int sz=q.size();
  11.             for(int i=1;i<sz;i++)
  12.             {
  13.                 TreeNode* cur=q.front();
  14.                 q.pop();
  15.                 if(cur->left)q.push(cur->left);
  16.                 if(cur->right)q.push(cur->right);
  17.             }
  18.             TreeNode* cur=q.front();
  19.             q.pop();
  20.             if(cur->left!=nullptr)q.push(cur->left);
  21.             if(cur->right!=nullptr)q.push(cur->right);
  22.             vec.emplace_back(cur->val);
  23.         }
  24.         return vec;
  25.     }
  26. };
复制代码
做法二:递归,实在就和二叉树层序遍历那题一样
  1. class Solution {
  2. public:
  3.     void bst(TreeNode* node,vector<int>& ans,int depth)
  4.     {
  5.         if(!node)return;
  6.         if(depth>ans.size())ans.push_back(node->val);
  7.         bst(node->right,ans,depth+1);
  8.         bst(node->left,ans,depth+1);
  9.     }
  10.     vector<int> rightSideView(TreeNode* root) {
  11.         if(!root)return {};
  12.         vector<int> ans;
  13.         bst(root,ans,1);
  14.         return ans;
  15.     }
  16. };
复制代码

二叉树展开为链表
做法一:按照前序遍历的次序来构造链表,以是先进行一次前序遍历,然后用一个vector存下来所有的节点。然后逐步遍历设置即可
  1. class Solution {
  2. public:
  3.     void preorder(TreeNode* root,vector<TreeNode*> &vec)
  4.     {
  5.         if(root)
  6.         {
  7.             vec.emplace_back(root);
  8.             preorder(root->left,vec);
  9.             preorder(root->right,vec);
  10.         }
  11.     }
  12.     void flatten(TreeNode* root) {
  13.         vector<TreeNode*> vec;
  14.         preorder(root,vec);
  15.         int n=vec.size();
  16.         for(int i=1;i<n;i++)
  17.         {
  18.             TreeNode* prev=vec[i-1],*cur=vec[i];
  19.             prev->left=nullptr;
  20.             prev->right=cur;
  21.         }
  22.         
  23.     }
  24. };
复制代码
做法二:空间复杂度O(1),对于一个节点,如果左子节点为空,则不必要操纵,如果不为空,那么对于右边,要找到左子树最右的节点,把右节点毗连上去,然后再把左子树连到右边即可。非常奇妙的做法
  1. class Solution {
  2. public:
  3.     void flatten(TreeNode* root) {
  4.         TreeNode* cur=root;
  5.         while(cur!=nullptr)
  6.         {
  7.             if(cur->left!=nullptr)
  8.             {
  9.                 auto next=cur->left;
  10.                 auto predecessor=next;
  11.                 while(predecessor->right!=nullptr)predecessor=predecessor->right;
  12.                 predecessor->right=cur->right;
  13.                 cur->left=nullptr;
  14.                 cur->right=next;
  15.             }
  16.             cur=cur->right;
  17.         }
  18.     }
  19. };
复制代码

从前序与中序遍历序列构造二叉树
做法一:递归,前序遍历第一个节点是根节点,中序遍历则是[左子树,根节点,右子树],我们可以先根据前序定位根节点,然后根据中序才能知道哪些在左边,哪些在右边。递归构建即可
  1. class Solution {
  2. public:
  3.     unordered_map<int,int> mp;
  4.     TreeNode* build(vector<int>& preorder,vector<int>& inorder,int pl,int pr,int il,int ir)
  5.     {
  6.         if(pl>pr)return nullptr;
  7.         int p_root=pl;
  8.         int in_root=mp[preorder[p_root]];
  9.         TreeNode* root=new TreeNode(preorder[p_root]);
  10.         int sz_l=in_root-il;
  11.         root->left=build(preorder,inorder,pl+1,pl+sz_l,il,in_root-1);
  12.         root->right=build(preorder,inorder,pl+sz_l+1,pr,in_root+1,ir);
  13.         return root;
  14.     }
  15.     TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
  16.         int n=preorder.size();
  17.         for(int i=0;i<n;i++)
  18.         {
  19.             mp[inorder[i]]=i;
  20.         }
  21.         return build(preorder,inorder,0,n-1,0,n-1);
  22.     }
  23. };
复制代码
做法二:迭代 先放养,因为肯定会忘记

路径总和III
做法一:直接遍历每个节点,对每个节点dfs看有几个满意的路径
  1. class Solution {
  2. public:
  3.     int rootsum(TreeNode* root,long long target)
  4.     {
  5.         if(!root)return 0;
  6.         int ans=0;
  7.         if(root->val==target)ans++;
  8.         ans+=rootsum(root->left,target-root->val);
  9.         ans+=rootsum(root->right,target-root->val);
  10.         return ans;
  11.     }
  12.     int pathSum(TreeNode* root, long long targetSum) {
  13.         if(!root)return 0;
  14.         int ans=rootsum(root,targetSum);
  15.         ans+=pathSum(root->left,targetSum);
  16.         ans+=pathSum(root->right,targetSum);
  17.         return ans;
  18.     }
  19. };
复制代码
做法二:可以利用前缀和,用哈希表将对应前缀和和数量对应起来。如果遍历到某一前缀和,前缀和-target的数量就是现在路径的总和为target的线路。要记得遍历前哈希加1,递归后面要减去1
  1. class Solution {
  2. public:
  3.     unordered_map<long long,int> pre;
  4.     int dfs(TreeNode *root,long long cur,int target)
  5.     {
  6.         if(!root)return 0;
  7.         int ans=0;
  8.         cur+=root->val;
  9.         if(pre.count(cur-target))
  10.         {
  11.             ans=pre[cur-target];//哈希表存储对应值有几个
  12.         }
  13.         pre[cur]++;
  14.         ans+=dfs(root->left,cur,target);
  15.         ans+=dfs(root->right,cur,target);
  16.         pre[cur]--;//因为遍历完左右子树就不存在这个前缀和了
  17.         return ans;
  18.     }
  19.     int pathSum(TreeNode* root, int targetSum) {
  20.         pre[0]=1;
  21.         return dfs(root,0,targetSum);
  22.     }
  23. };
复制代码

二叉树的最近公共祖先 想起数链剖分了
做法一:哈希表
  1. class Solution {
  2. public:
  3.     unordered_map<int,TreeNode*>fa;
  4.     unordered_map<int,bool>vis;
  5.     void dfs(TreeNode* root)
  6.     {
  7.         if(root->left)
  8.         {
  9.             fa[root->left->val]=root;
  10.             dfs(root->left);
  11.         }
  12.         if(root->right)
  13.         {
  14.             fa[root->right->val]=root;
  15.             dfs(root->right);
  16.         }
  17.     }
  18.     TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
  19.         fa[root->val]=nullptr;
  20.         dfs(root);
  21.         while(p!=nullptr)
  22.         {
  23.             vis[p->val]=true;
  24.             p=fa[p->val];
  25.         }
  26.         while(q!=nullptr)
  27.         {
  28.             if(vis[q->val])return q;
  29.             q=fa[q->val];
  30.         }
  31.         return nullptr;
  32.     }
  33. };
复制代码

二叉树中的最大路径和
做法:由于不能向上面走,以是不是树形dp。只必要递归即可。对于空节点,那么就是贡献度为0,递归的时间,要比力,该节点加左子树和右子树的和是否大于maxum,返回的不是和而是节点值加上max(left,right),因为每个节点至多只出现一次
  1. class Solution {
  2. public:
  3.     int maxSum=INT_MIN;
  4.     int maxsum(TreeNode* root)
  5.     {
  6.         if(!root)return 0;
  7.         int sum=root->val;
  8.         int leftsum=maxsum(root->left);
  9.         int rightsum=maxsum(root->right);
  10.         //maxSum=max(maxSum,leftsum);
  11.         //maxSum=max(maxSum,rightsum);
  12.         if(leftsum>0)sum+=leftsum;
  13.         else leftsum=0;
  14.         if(rightsum>0)sum+=rightsum;
  15.         else rightsum=0;
  16.         maxSum=max(maxSum,sum);
  17.         return root->val+max(leftsum,rightsum);
  18.     }
  19.     int maxPathSum(TreeNode* root) {
  20.         maxsum(root);
  21.         return maxSum;
  22.     }
  23. };
复制代码

岛屿数量
做法一:深度优先遍历,搜寻到一个节点,我们可以dfs周边满意条件的节点,如许就能把一整个岛屿全部化为海水。dfs了几次就代表有几个岛屿
  1. class Solution {
  2. public:
  3.     void dfs(vector<vector<char>>& grid,int r,int c)
  4.     {
  5.         int nr=grid.size();
  6.         int nc=grid[0].size();
  7.         grid[r][c]='0';
  8.         if(r-1>=0&&grid[r-1][c]=='1')dfs(grid,r-1,c);
  9.         if(r+1<nr&&grid[r+1][c]=='1')dfs(grid,r+1,c);
  10.         if(c-1>=0&&grid[r][c-1]=='1')dfs(grid,r,c-1);
  11.         if(c+1<nc&&grid[r][c+1]=='1')dfs(grid,r,c+1);
  12.     }
  13.     int numIslands(vector<vector<char>>& grid) {
  14.         int nr=grid.size();
  15.         if(!nr)return 0;
  16.         int nc=grid[0].size();
  17.         int num=0;
  18.         for(int r=0;r<nr;r++)
  19.             for(int c=0;c<nc;c++)
  20.             {
  21.                 if(grid[r][c]=='1')
  22.                 {
  23.                     num++;
  24.                     dfs(grid,r,c);
  25.                 }
  26.             }
  27.         return num;
  28.     }
  29. };
复制代码
做法二:BFS实在差不多,也是加入pair构成的队列
做法三:好像能用并查集吧 我不会

腐烂的橘子
做法:BFS
  1. class Solution {
  2. public:
  3.     int cnt;
  4.     int dis[10][10];
  5.     int dir_x[4]={0,1,0,-1};
  6.     int dir_y[4]={1,0,-1,0};
  7.     int orangesRotting(vector<vector<int>>& grid) {
  8.        queue<pair<int,int>>q;
  9.        cnt=0;
  10.        int n=grid.size();
  11.        int m=grid[0].size();
  12.        for(int i=0;i<n;i++)
  13.         for(int j=0;j<m;j++)
  14.         {
  15.             if(grid[i][j]==2)
  16.             {
  17.                 q.push({i,j});
  18.                 //dis[i][j]=0;
  19.             }
  20.             else if(grid[i][j]==1)
  21.             {
  22.                 cnt++;
  23.             }
  24.         }
  25.         if(q.empty()&&cnt)return -1;
  26.         int ans=0;
  27.         while(!q.empty())
  28.         {
  29.            int t=q.size();
  30.            for(int k=0;k<t;k++)
  31.            {
  32.             pair<int,int> p=q.front();
  33.             q.pop();
  34.             for(int i=0;i<4;i++)
  35.             {
  36.                 int x=p.first+dir_x[i];
  37.                 int y=p.second+dir_y[i];
  38.                 if(x>=0&&x<n&&y>=0&&y<m&&grid[x][y]==1)
  39.                 {
  40.                 grid[x][y]=2;
  41.                 q.push({x,y});
  42.                 cnt--;
  43.                  }
  44.             }
  45.                
  46.             
  47.             }
  48.             if(!q.empty())ans++;
  49.         }
  50.         if(cnt)return -1;
  51.         return ans;
  52.     }
  53. };
复制代码

课程表
做法一:拓扑排序
  1. class Solution {
  2. public:
  3.     int du[2010];
  4.     unordered_map<int,vector<int>>mp;
  5.     bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
  6.         for(auto cur:prerequisites)
  7.         {
  8.             du[cur[1]]++;
  9.             mp[cur[0]].push_back(cur[1]);
  10.         }
  11.         queue<int> q;
  12.         for(int i=0;i<numCourses;i++)
  13.         {
  14.             if(du[i]==0)q.push(i);
  15.         }
  16.         while(!q.empty())
  17.         {
  18.             int u=q.front();
  19.             q.pop();
  20.             numCourses--;
  21.             for(auto num:mp[u])
  22.             {
  23.                 du[num]--;
  24.                 if(du[num]==0)q.push(num);
  25.             }
  26.         }
  27.         if(numCourses==0)return true;
  28.         return false;
  29.     }
  30. };
复制代码


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

冬雨财经

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表