递归问题也是做的不好,总去想每一层调用发生了什么,导致越想越乱。
看到一篇博客写的非常好,记录总结。
原文地址: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;
}
};
京公网安备 11010502036488号