斐波那契数列:
n=0,f(n)=0,n=1,f(n)=1
f(n) = f(n-1) + f(n-2)
递归解法:
int Fibonacci(int n)
{
if(n <= 1)
{
return n;
}
else
{
return Fibonacci(n - 1) + Fibonacci(n - 2);
}
}
问题:n过大容易导致栈溢出,改为循环
int Fibonacci(int n) {
// 非常容易理解,0,1,2的时候单独处理
if(n <= 0){
return 0;
}
if(n == 1 || n ==2){
return 1;
}
int a = 1;
int b = 1;
int result;
// 然后处理的时候获取到A+B的结果,然后把B赋值给A,结果赋值给B,一步步忘后面移动
for(int i = 3;i<=n;i++){
result = a + b;
a = b;
b = result;
}
return result;
}
青蛙变态跳台阶问题:
一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
由于每次跳的阶数不确定,没有一个固定的规律,但是可以了解的是后一次跳是在前一次跳的结果上累加的,因此我们可以考虑使用递归的方法来解决问题。
那么从递归的三个步骤开始寻找解决方案:
1. 递归截止条件。
由于每次可以跳1-n的任意阶数,因此无论有多少阶,都可以一次跳完,为了表示方便,我们将一次性跳完的情况设为F(0),当n=1时,只能有一种情况,F(1) = 1。当n=2时,可以每次跳1阶,也可以一次跳两阶,则F(2) = 2。
2. 递归的前后衔接。
假设现在又n阶,可以跳完n阶的情况分别是:一次跳完F(0);先跳一步F(1),后面还有F(n-1)种跳法;或者先跳两步F(2),后面还有F(n-2)种跳法。依次类推,第一次跳出n阶后,后面还有 F(n-n)中跳法。可以得出:
F(n) = F(n-1)+F(n-2)+F(n-3)+..........+F(0)=2F(n-1)
递归写法:
int jumpFloorII(int number) {
if(number<=0)
return 0;
else if(number==1)
return 1;
else
return 2*jumpFloorII(number-1);
}
循环写法:
int JumpFloorII(int target) {
if(target==0||target==1)
return 1;
if(target==2)
return 2;
int sum = 0;
for(int i=0;i<target;i++){
sum += JumpFloorII(i);
}
return sum;
}
合并两个排序链表:
输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。
ListNode* Merge(ListNode* pHead1, ListNode* pHead2)
{
if(pHead1==nullptr)
return pHead2;
else if(pHead2==nullptr)
return pHead1;
ListNode* pMerge=nullptr;
if(pHead1->val>pHead2->val){
pMerge=pHead2;
pMerge->next=Merge(pHead1,pHead2->next);
}
else{
pMerge=pHead1;
pMerge->next=Merge(pHead1->next,pHead2);
}
return pMerge;
}
二叉树的深度:
输入一棵二叉树,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。
int TreeDepth(TreeNode* pRoot)
{
if(pRoot==nullptr)
return 0;
int nleft=TreeDepth(pRoot->left);
int nright=TreeDepth(pRoot->right);
return (nleft>nright)?(nleft+1):(nright+1);
}
二叉树的镜像:
void Mirror(TreeNode *pRoot) {
if(pRoot){
TreeNode *tmp = pRoot->left;
pRoot->left = pRoot->right;
pRoot->right = tmp;
Mirror(pRoot->left);
Mirror(pRoot->right);
}
return ;
}
对称二叉树:
给定一个二叉树,判断是否为对称二叉树。
bool isSymmetrical(TreeNode* pRoot1, TreeNode* pRoot2){//递归判断两个左右子树是否对称
if (pRoot1 == NULL && pRoot2 == NULL){//如果均为空,说明相等,是对称的
return true;
}
if (pRoot1 == NULL || pRoot2 == NULL){//如果有一个为空,另一个不为空,说明不对称
return false;
}
if (pRoot1->val != pRoot2->val){//都不为空时,判断值是否相等,再递归判断左右子树
return false;
}
return (isSymmetrical(pRoot1->left, pRoot2->right) &&
(isSymmetrical(pRoot1->right, pRoot2->left)));
}
一般二叉树的最低公共祖先
当遍历到一个root点的时候,
1.判断root是不是null如果root为null,那么就无所谓祖先节点,直接返回null就好了
2.如果root的左子树存在p,右子树存在q,那么root肯定就是最近祖先
3.如果pq都在root的左子树,那么就需要递归root的左子树,右子树同理
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if(root == NULL || root == p || root ==q)
return root;
TreeNode* left = lowestCommonAncestor(root->left, p, q);
TreeNode* right = lowestCommonAncestor(root->right, p, q);
if(left && right){
return root;
}
else
{
return left == NULL ? right : left;
}
}
树的子结构(两重递归):
输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)
bool DoseTree1HaveTree2(TreeNode* pRoot1,TreeNode* pRoot2){
if(pRoot2==nullptr)
return true;
if(pRoot1==nullptr)
return false;
if(pRoot1->val!=pRoot2->val)
return false;
return DoseTree1HaveTree2(pRoot1->left,pRoot2->left)&&
DoseTree1HaveTree2(pRoot1->right,pRoot2->right);
}
bool HasSubtree(TreeNode* pRoot1, TreeNode* pRoot2)
{
bool result=false;
if(pRoot1!=nullptr&&pRoot2!=nullptr)
{
if(pRoot1->val==pRoot2->val)
result=DoseTree1HaveTree2(pRoot1,pRoot2);
if(result==0)
result=HasSubtree(pRoot1->left,pRoot2);
if(result==0)
result=HasSubtree(pRoot1->right,pRoot2);
}
return result;
}