马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
x
翻转二叉树
做法:递归即可,留意判断为空
- class Solution {
- public:
- TreeNode* invertTree(TreeNode* root) {
- if(root==nullptr)return nullptr;
- TreeNode* node=root->left;
- root->left=invertTree(root->right);
- root->right=invertTree(node);
- return root;
- }
- };
复制代码 对称二叉树
做法一:递归。使用两个不同的指针进入递归即可
- class Solution {
- public:
- bool check(TreeNode* p,TreeNode* q)
- {
- if(!p&&!q)return true;
- if(!p||!q)return false;
- return p->val==q->val&&check(p->left,q->right)&&check(p->right,q->left);
- }
- bool isSymmetric(TreeNode* root) {
- return check(root->left,root->right);
- }
- };
复制代码 做法二:迭代。一开始想用deque,但卡在了迭代怎么能让同一层进行比力,后面看了题解才知道可以直接用queue,只要压入的时间保证次序即可
- class Solution {
- public:
- bool check(TreeNode* u, TreeNode* v) {
- queue<TreeNode*> q;
- q.push(u);
- q.push(v);
- while(!q.empty())
- {
- u=q.front();
- q.pop();
- v=q.front();
- q.pop();
- if(!u&&!v)continue;
- if((!u||!v)||(u->val!=v->val))return false;
- q.push(u->left);
- q.push(v->right);
- q.push(u->right);
- q.push(v->left);
- }
- return true;
- }
- bool isSymmetric(TreeNode* root) {
- return check(root->left,root->right);
- }
- };
复制代码 二叉树的直径
做法:一开始想用树形dp,但发现搞复杂了根本不用。实在最直观的思想就是,对每个节点依次遍历,然后求左子树和右子树深度,然后进行比力。但我们可以发现,在这一过程中,重复搜刮了很多地方。要么影象化搜刮,要么就直接在递归中比力即可,如许就只必要递归一次。
- class Solution {
- public:
- int ans=0;
- int depth(TreeNode* root)
- {
- if(root==nullptr)return 0;
- int L=depth(root->left);
- int R=depth(root->right);
- ans=max(ans,L+R+1);
- return max(L,R)+1;
- }
- int diameterOfBinaryTree(TreeNode* root) {
- depth(root);
- return ans-1;
- }
- };
复制代码 二叉树的层序遍历
做法一:迭代,BFS,记录一下每层的节点个数即可
- class Solution {
- public:
- vector<vector<int>> levelOrder(TreeNode* root) {
- if(root==nullptr)return {};
- vector<vector<int>> vec;
- queue<TreeNode*>q;
- q.push(root);
- while(!q.empty())
- {
- vector<int> v;
- int sz=q.size();
- for(int i=1;i<=sz;i++)
- {
- auto u=q.front();
- q.pop();
- if(u->left!=nullptr)q.push(u->left);
- if(u->right!=nullptr)q.push(u->right);
- v.emplace_back(u->val);
- }
- vec.emplace_back(v);
- }
- return vec;
- }
- };
复制代码 做法二:递归,这个想法很精妙
- class Solution {
- private:
- vector<vector<int>> ret;
- public:
- vector<vector<int>> levelOrder(TreeNode* root) {
- dfs(root,0);
- return ret;
- }
- void dfs(TreeNode* root,int deep)
- {
- if(root == nullptr) return;
- if(deep>=ret.size()) ret.push_back({root->val});
- else ret[deep].push_back(root->val);
- dfs(root->left,deep+1);
- dfs(root->right,deep+1);
- }
- };
复制代码 将有序数组转换为二叉搜刮树
做法:每次建立中间节点即可,然后递归建立树
- class Solution {
- public:
- TreeNode* build(vector<int>& nums,int left,int right)
- {
- if(left>right)return nullptr;
- int mid=(left+right)>>1;
- TreeNode* root=new TreeNode(nums[mid]);
- root->left=build(nums,left,mid-1);
- root->right=build(nums,mid+1,right);
- return root;
- }
- TreeNode* sortedArrayToBST(vector<int>& nums) {
- return build(nums,0,nums.size()-1);
- }
- };
复制代码 验证二叉搜刮树
做法一:分别dfs两边的子树,如果不满意条件就返回false
- class Solution {
- public:
- bool dfs(TreeNode* root,long long lower,long long upper)
- {
- if(root==nullptr)return true;
- if(root->val<=lower||root->val>=upper)return false;
- return dfs(root->left,lower,root->val)&&dfs(root->right,root->val,upper);
- }
- bool isValidBST(TreeNode* root) {
- return dfs(root,LONG_MIN,LONG_MAX);
- }
- };
复制代码 做法二:中序遍历。这里可以递归大概不递归都可以
- class Solution {
- public:
- vector<int> vec;
- bool flag=true;
- void dfs(TreeNode* root)
- {
- if(root==nullptr)return;
- dfs(root->left);
- if(vec.size()&&vec.back()>=root->val)
- {
- flag=false;
- return;
- }
- vec.emplace_back(root->val);
- dfs(root->right);
- }
- bool isValidBST(TreeNode* root) {
- dfs(root);
- return flag;
- }
- };
复制代码 二叉搜刮树中第k小的元素
做法一:非优化。简单直接的中序遍历,刚好练一下非递归
- class Solution {
- public:
- int kthSmallest(TreeNode* root, int k) {
- int cnt=0;
- stack<TreeNode*> s;
- while(root!=nullptr||!s.empty())
- {
- if(root!=nullptr)
- {
- s.push(root);
- root=root->left;
- }
- else
- {
- root=s.top();
- s.pop();
- cnt++;
- if(cnt==k)return root->val;
- root=root->right;
- }
- }
- return -1;
- }
- };
复制代码 做法二:如果要频繁访问第k小的数字,可以通过预处理节点数,有点雷同快排找第k个大的
- class Solution {
- public:
- unordered_map<TreeNode*,int>nodenum;
- int countnodenum(TreeNode* node)
- {
- if(node==nullptr)return 0;
- nodenum[node]=1+countnodenum(node->left)+countnodenum(node->right);
- return nodenum[node];
- }
- int getnodenum(TreeNode* node)
- {
- if(node!=nullptr&&nodenum.count(node))
- {
- return nodenum[node];
- }
- return 0;
- }
-
- int kthSmallest(TreeNode* root, int k) {
- countnodenum(root);
- while(root!=nullptr)
- {
- int left=getnodenum(root->left);
- if(left<k-1)
- {
- root=root->right;
- k-=left+1;
- }
- else if(left==k-1)break;
- else root=root->left;
- }
- return root->val;
- }
- };
复制代码 二叉树的右视图
做法一:迭代,广度优先遍历即可
- class Solution {
- public:
- vector<int> rightSideView(TreeNode* root) {
- if(root==nullptr)return {};
- queue<TreeNode*> q;
- vector<int> vec;
- q.push(root);
- while(!q.empty())
- {
- int sz=q.size();
- for(int i=1;i<sz;i++)
- {
- TreeNode* cur=q.front();
- q.pop();
- if(cur->left)q.push(cur->left);
- if(cur->right)q.push(cur->right);
- }
- TreeNode* cur=q.front();
- q.pop();
- if(cur->left!=nullptr)q.push(cur->left);
- if(cur->right!=nullptr)q.push(cur->right);
- vec.emplace_back(cur->val);
- }
- return vec;
- }
- };
复制代码 做法二:递归,实在就和二叉树层序遍历那题一样
- class Solution {
- public:
- void bst(TreeNode* node,vector<int>& ans,int depth)
- {
- if(!node)return;
- if(depth>ans.size())ans.push_back(node->val);
- bst(node->right,ans,depth+1);
- bst(node->left,ans,depth+1);
- }
- vector<int> rightSideView(TreeNode* root) {
- if(!root)return {};
- vector<int> ans;
- bst(root,ans,1);
- return ans;
- }
- };
复制代码 二叉树展开为链表
做法一:按照前序遍历的次序来构造链表,以是先进行一次前序遍历,然后用一个vector存下来所有的节点。然后逐步遍历设置即可
- class Solution {
- public:
- void preorder(TreeNode* root,vector<TreeNode*> &vec)
- {
- if(root)
- {
- vec.emplace_back(root);
- preorder(root->left,vec);
- preorder(root->right,vec);
- }
- }
- void flatten(TreeNode* root) {
- vector<TreeNode*> vec;
- preorder(root,vec);
- int n=vec.size();
- for(int i=1;i<n;i++)
- {
- TreeNode* prev=vec[i-1],*cur=vec[i];
- prev->left=nullptr;
- prev->right=cur;
- }
-
- }
- };
复制代码 做法二:空间复杂度O(1),对于一个节点,如果左子节点为空,则不必要操纵,如果不为空,那么对于右边,要找到左子树最右的节点,把右节点毗连上去,然后再把左子树连到右边即可。非常奇妙的做法
- class Solution {
- public:
- void flatten(TreeNode* root) {
- TreeNode* cur=root;
- while(cur!=nullptr)
- {
- if(cur->left!=nullptr)
- {
- auto next=cur->left;
- auto predecessor=next;
- while(predecessor->right!=nullptr)predecessor=predecessor->right;
- predecessor->right=cur->right;
- cur->left=nullptr;
- cur->right=next;
- }
- cur=cur->right;
- }
- }
- };
复制代码 从前序与中序遍历序列构造二叉树
做法一:递归,前序遍历第一个节点是根节点,中序遍历则是[左子树,根节点,右子树],我们可以先根据前序定位根节点,然后根据中序才能知道哪些在左边,哪些在右边。递归构建即可
- class Solution {
- public:
- unordered_map<int,int> mp;
- TreeNode* build(vector<int>& preorder,vector<int>& inorder,int pl,int pr,int il,int ir)
- {
- if(pl>pr)return nullptr;
- int p_root=pl;
- int in_root=mp[preorder[p_root]];
- TreeNode* root=new TreeNode(preorder[p_root]);
- int sz_l=in_root-il;
- root->left=build(preorder,inorder,pl+1,pl+sz_l,il,in_root-1);
- root->right=build(preorder,inorder,pl+sz_l+1,pr,in_root+1,ir);
- return root;
- }
- TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
- int n=preorder.size();
- for(int i=0;i<n;i++)
- {
- mp[inorder[i]]=i;
- }
- return build(preorder,inorder,0,n-1,0,n-1);
- }
- };
复制代码 做法二:迭代 先放养,因为肯定会忘记
路径总和III
做法一:直接遍历每个节点,对每个节点dfs看有几个满意的路径
- class Solution {
- public:
- int rootsum(TreeNode* root,long long target)
- {
- if(!root)return 0;
- int ans=0;
- if(root->val==target)ans++;
- ans+=rootsum(root->left,target-root->val);
- ans+=rootsum(root->right,target-root->val);
- return ans;
- }
- int pathSum(TreeNode* root, long long targetSum) {
- if(!root)return 0;
- int ans=rootsum(root,targetSum);
- ans+=pathSum(root->left,targetSum);
- ans+=pathSum(root->right,targetSum);
- return ans;
- }
- };
复制代码 做法二:可以利用前缀和,用哈希表将对应前缀和和数量对应起来。如果遍历到某一前缀和,前缀和-target的数量就是现在路径的总和为target的线路。要记得遍历前哈希加1,递归后面要减去1
- class Solution {
- public:
- unordered_map<long long,int> pre;
- int dfs(TreeNode *root,long long cur,int target)
- {
- if(!root)return 0;
- int ans=0;
- cur+=root->val;
- if(pre.count(cur-target))
- {
- ans=pre[cur-target];//哈希表存储对应值有几个
- }
- pre[cur]++;
- ans+=dfs(root->left,cur,target);
- ans+=dfs(root->right,cur,target);
- pre[cur]--;//因为遍历完左右子树就不存在这个前缀和了
- return ans;
- }
- int pathSum(TreeNode* root, int targetSum) {
- pre[0]=1;
- return dfs(root,0,targetSum);
- }
- };
复制代码 二叉树的最近公共祖先 想起数链剖分了
做法一:哈希表
- class Solution {
- public:
- unordered_map<int,TreeNode*>fa;
- unordered_map<int,bool>vis;
- void dfs(TreeNode* root)
- {
- if(root->left)
- {
- fa[root->left->val]=root;
- dfs(root->left);
- }
- if(root->right)
- {
- fa[root->right->val]=root;
- dfs(root->right);
- }
- }
- TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
- fa[root->val]=nullptr;
- dfs(root);
- while(p!=nullptr)
- {
- vis[p->val]=true;
- p=fa[p->val];
- }
- while(q!=nullptr)
- {
- if(vis[q->val])return q;
- q=fa[q->val];
- }
- return nullptr;
- }
- };
复制代码 二叉树中的最大路径和
做法:由于不能向上面走,以是不是树形dp。只必要递归即可。对于空节点,那么就是贡献度为0,递归的时间,要比力,该节点加左子树和右子树的和是否大于maxum,返回的不是和而是节点值加上max(left,right),因为每个节点至多只出现一次
- class Solution {
- public:
- int maxSum=INT_MIN;
- int maxsum(TreeNode* root)
- {
- if(!root)return 0;
- int sum=root->val;
- int leftsum=maxsum(root->left);
- int rightsum=maxsum(root->right);
- //maxSum=max(maxSum,leftsum);
- //maxSum=max(maxSum,rightsum);
- if(leftsum>0)sum+=leftsum;
- else leftsum=0;
- if(rightsum>0)sum+=rightsum;
- else rightsum=0;
- maxSum=max(maxSum,sum);
- return root->val+max(leftsum,rightsum);
- }
- int maxPathSum(TreeNode* root) {
- maxsum(root);
- return maxSum;
- }
- };
复制代码 岛屿数量
做法一:深度优先遍历,搜寻到一个节点,我们可以dfs周边满意条件的节点,如许就能把一整个岛屿全部化为海水。dfs了几次就代表有几个岛屿
- class Solution {
- public:
- void dfs(vector<vector<char>>& grid,int r,int c)
- {
- int nr=grid.size();
- int nc=grid[0].size();
- grid[r][c]='0';
- if(r-1>=0&&grid[r-1][c]=='1')dfs(grid,r-1,c);
- if(r+1<nr&&grid[r+1][c]=='1')dfs(grid,r+1,c);
- if(c-1>=0&&grid[r][c-1]=='1')dfs(grid,r,c-1);
- if(c+1<nc&&grid[r][c+1]=='1')dfs(grid,r,c+1);
- }
- int numIslands(vector<vector<char>>& grid) {
- int nr=grid.size();
- if(!nr)return 0;
- int nc=grid[0].size();
- int num=0;
- for(int r=0;r<nr;r++)
- for(int c=0;c<nc;c++)
- {
- if(grid[r][c]=='1')
- {
- num++;
- dfs(grid,r,c);
- }
- }
- return num;
- }
- };
复制代码 做法二:BFS实在差不多,也是加入pair构成的队列
做法三:好像能用并查集吧 我不会
腐烂的橘子
做法:BFS
- class Solution {
- public:
- int cnt;
- int dis[10][10];
- int dir_x[4]={0,1,0,-1};
- int dir_y[4]={1,0,-1,0};
- int orangesRotting(vector<vector<int>>& grid) {
- queue<pair<int,int>>q;
- cnt=0;
- int n=grid.size();
- int m=grid[0].size();
- for(int i=0;i<n;i++)
- for(int j=0;j<m;j++)
- {
- if(grid[i][j]==2)
- {
- q.push({i,j});
- //dis[i][j]=0;
- }
- else if(grid[i][j]==1)
- {
- cnt++;
- }
- }
- if(q.empty()&&cnt)return -1;
- int ans=0;
- while(!q.empty())
- {
- int t=q.size();
- for(int k=0;k<t;k++)
- {
- pair<int,int> p=q.front();
- q.pop();
- for(int i=0;i<4;i++)
- {
- int x=p.first+dir_x[i];
- int y=p.second+dir_y[i];
- if(x>=0&&x<n&&y>=0&&y<m&&grid[x][y]==1)
- {
- grid[x][y]=2;
- q.push({x,y});
- cnt--;
- }
- }
-
-
- }
- if(!q.empty())ans++;
- }
- if(cnt)return -1;
- return ans;
- }
- };
复制代码 课程表
做法一:拓扑排序
- class Solution {
- public:
- int du[2010];
- unordered_map<int,vector<int>>mp;
- bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
- for(auto cur:prerequisites)
- {
- du[cur[1]]++;
- mp[cur[0]].push_back(cur[1]);
- }
- queue<int> q;
- for(int i=0;i<numCourses;i++)
- {
- if(du[i]==0)q.push(i);
- }
- while(!q.empty())
- {
- int u=q.front();
- q.pop();
- numCourses--;
- for(auto num:mp[u])
- {
- du[num]--;
- if(du[num]==0)q.push(num);
- }
- }
- if(numCourses==0)return true;
- return false;
- }
- };
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |