递归问题也是做的不好,总去想每一层调用发生了什么,导致越想越乱。
看到一篇博客写的非常好,记录总结。
原文地址:https://lyl0724.github.io/2020/01/25/1/
另一篇:https://mp.weixin.qq.com/s/-V0jBkPoZHYC2jLfSnQ6-g
解递归题的三部曲:
1、找整个递归的终止条件:递归应该在什么时候结束?
2、找返回值:应该给上一级返回什么信息?
3、本级递归应该做什么:在这一级递归中,应该完成什么任务?
需要总结的题目:
Leetcode 101. 对称二叉树
Leetcode 111. 二叉树的最小深度
Leetcode 226. 翻转二叉树:这个题的备注是最骚的。Mac OS下载神器homebrew的大佬作者去面试谷歌,没做出来这道算法题,然后被谷歌面试官怼了:”我们90%的工程师使用您编写的软件(Homebrew),但是您却无法在面试时在白板上写出翻转二叉树这道题,这太糟糕了。”
Leetcode 617. 合并二叉树
Leetcode 654. 最大二叉树
Leetcode 83. 删除排序链表中的重复元素
目标:9.17号之前完成。
二叉树的最小深度
给定一个二叉树,找出其最小深度。最小深度是从根节点到最近叶子节点的最短路径上的节点数量。说明: 叶子节点是指没有子节点的节点。
思路:
1、终止条件
2、返回值
3、当前操作
//注意如果根节点的左或右子树为空的话是构不成子树的。而最小深度是要求从根节点到子树的。当左或右子树为空时,不符合要求。 class Solution { public: int minDepth(TreeNode* root) { if (!root) return 0; //递归结束 int left = minDepth(root->left); //计算左子树的高度 int right = minDepth(root->right); //计算右子树的高度 if (!left || !right) return left + right + 1; //如果有一个空,则+1 return min(left, right) + 1; //否则最小值+1 } };
翻转二叉树
1、终止条件 NULL
2、返回值 跟节点
3、操作 交换左右子树
以下为前序遍历
class Solution { public: TreeNode* invertTree(TreeNode* root) {//先序优先遍历 if(root==NULL) return root; // 遍历到null节点时,不用翻转,直接返回它本身 TreeNode* temp = root->left; root->left = root->right; root->right = temp; invertTree(root->left); invertTree(root->right); return root; } };
合并二叉树
合并这类问题需要注意的是,如果有一棵树为空,则返回另一棵树。
不修改树的结构
class Solution { public: TreeNode* mergeTrees(TreeNode* t1, TreeNode* t2) { if (t1 == NULL) return t2; if (t2 == NULL) return t1; // 重新定义新的节点,不修改原有两个树的结构 TreeNode* root = new TreeNode(0); root->val = t1->val + t2->val; root->left = mergeTrees(t1->left, t2->left); root->right = mergeTrees(t1->right, t2->right); return root; } };
修改树的结构,思路都是一样的
class Solution { public: TreeNode* mergeTrees(TreeNode* t1, TreeNode* t2) { if (t1 == NULL) return t2; if (t2 == NULL) return t1; // 修改了t1的数值和结构 t1->val += t2->val; t1->left = mergeTrees(t1->left, t2->left); t1->right = mergeTrees(t1->right, t2->right); return t1; } };
删除排序链表中的重复元素
之前也总结了指针法,这回事递归法。
递归套路解决链表问题:
找终止条件:当head指向链表只剩一个元素的时候,自然是不可能重复的,因此return
想想应该返回什么值:应该返回的自然是已经去重的链表的头节点
每一步要做什么:宏观上考虑,此时head.next已经指向一个去重的链表了,而根据第二步,我应该返回一个去重的链表的头节点。因此这一步应该做的是判断当前的head和head.next是否相等,如果相等则说明重了,返回head.next,否则返回head
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode* deleteDuplicates(ListNode* head) { if(!head||!head->next) return head; head ->next = deleteDuplicates(head ->next); if(head ->val == head ->next ->val) head = head ->next; return head; } };