二叉树中最长连续子序列的长度

问题:最长连续子序列是指:子节点的值大于父节点的值。

思路1:设置一个全局变量,记录树遍历时的最大连续长度,然后递归地求解树的长度,时间复杂度为O(n)

思路2:将每个结点作为根结点,依次求取每个结点的的最大连续子序列长度。时间复杂度为O(n^2)

相关程序实现:

思路1的相关程序实现:

#include <iostream>
#include<malloc.h>

using namespace std;
static int length=0;

typedef struct Btree
{
    int num;
    struct Btree *lchild;
    struct Btree *rchild;
} *PBtree,Btree;


void inorder( PBtree root)
{
    if(root==NULL)
        return;
    else
    {
        inorder(root->lchild);
        cout<<root->num<<" ";
        inorder(root->rchild);
    }
}

//从根节点开始记录满足条件的长度
int getLong(PBtree root)
{
    if(root==NULL)
        return 0;
    int res=-1;
    if(root->lchild&&(root->lchild)->num>root->num)
        res=max(res,getLong(root->lchild)+1);
    if(root->rchild&&(root->rchild)->num>root->num)
        res=max(res,getLong(root->rchild));
    return res;
}

//在所有的路径中选择满足条件的最大长度
int getLongSubList(PBtree root)
{
    if(root==NULL)
        return 0;
    int res=getLong(root);
    if(root->lchild)
        res=max(res,getLongSubList(root->lchild));
    if(root->rchild)
        res=max(res,getLongSubList(root->rchild));
    return res+1;
}

int main()
{
    PBtree root=NULL;
    PBtree a1=new  Btree();
    PBtree a2=new  Btree();
    PBtree a3=new  Btree();
    PBtree a4=new  Btree();
    PBtree a5=new  Btree();
    PBtree a6=new  Btree();
    PBtree a7=new  Btree();
    PBtree a8=new  Btree();

    a1->num=10;
    a2->num=1;
    a3->num=2;
    a4->num=3;
    a5->num=4;
    a6->num=6;
    a7->num=1;
    a8->num=2;

    a1->lchild=a2;
    a1->rchild=a3;

    a2->lchild=a4;
    a4->lchild=a5;
    a5->lchild=a6;

    a3->lchild=a7;
    a7->lchild=a8;

    inorder(a1);
    cout<<endl;
    cout<<getLongSubList(a1)<<endl;
    return 0;
}

输出结果:

6 4 3 1 10 2 1 2
4

思路2的相关程序实现:

#include <iostream>
#include<malloc.h>

using namespace std;
static int length=0;

typedef struct Btree
{
    int num;
    struct Btree *lchild;
    struct Btree *rchild;
} *PBtree,Btree;


void inorder( PBtree root)
{
    if(root==NULL)
        return;
    else
    {
        inorder(root->lchild);
        cout<<root->num<<" ";
        inorder(root->rchild);
    }
}


//从根节点开始记录满足条件的长度
int getLong(PBtree root)
{
    if(root==NULL)
        return 0;

    if(root->lchild==NULL&&root->rchild==NULL)
    {
        length= max(length,1);
        //cout<<length<<endl;
        return 1;
    }

    int left_num=getLong(root->lchild);
    int right_num=getLong(root->rchild);

    if(root->lchild&&(root->lchild)->num>root->num)
        left_num++;
    if(root->rchild&&(root->rchild)->num>root->num)
        right_num++;
    if((root->lchild&&(root->lchild)->num<root->num)&&(root->rchild&&(root->rchild)->num<root->num))
    {
        length=max(length,1);
        //cout<<length<<endl;
        return 1;
    }
    length=max(length,max(left_num,right_num));
    //cout<<length<<endl;
    return max(left_num,right_num);
}

int main()
{
    PBtree root=NULL;
    PBtree a1=new  Btree();
    PBtree a2=new  Btree();
    PBtree a3=new  Btree();
    PBtree a4=new  Btree();
    PBtree a5=new  Btree();
    PBtree a6=new  Btree();
    PBtree a7=new  Btree();
    PBtree a8=new  Btree();

    a1->num=10;
    a2->num=1;
    a3->num=2;
    a4->num=3;
    a5->num=4;
    a6->num=6;
    a7->num=1;
    a8->num=2;

    a1->lchild=a2;
    a1->rchild=a3;

    a2->lchild=a4;
    a4->lchild=a5;
    a5->lchild=a6;

    a3->lchild=a7;
    a7->lchild=a8;

    inorder(a1);
    cout<<endl;
    cout<<getLongSubList(a1)<<endl;

    return 0;
}

输出结果:

6 4 3 1 10 2 1 2
4

总结:

树的遍历是自底向上的,每次都是先子树,在向上回溯。(先得到叶子节点的信息,然后逐次得到根的信息)

对于一棵二叉树,我们可以定义其最长连续子序列(LCS)为从根节点开始,沿着任意路径向下遍历,使得经过的结点值连续递增或递减的最长路径长度。 为了求解二叉树的 LCS,我们可以使用递归的思想。具体来说,我们可以定义一个递归函数 dfs,其参数为当前结点和上一个结点的值 pre,并返回以当前结点为结尾的 LIS 长度和 LDS 长度。对于一个结点 node,如果 node.val = pre + 1,则可以将当前结点加入到 LIS ;如果 node.val = pre - 1,则可以将当前结点加入到 LDS 。如果 node.val 既不是 pre + 1 也不是 pre - 1,则需要重新开始计算 LCS 长度。最终的 LCS 长度即为所有以各个结点为结尾的 LIS 和 LDS 长度的最大值。 下面是一个 Java 代码实现: ```java class TreeNode { int val; TreeNode left; TreeNode right; TreeNode(int x) { val = x; } } class Solution { public int longestConsecutive(TreeNode root) { if (root == null) { return 0; } int[] res = dfs(root, root.val - 1); return Math.max(res[0], res[1]); } private int[] dfs(TreeNode node, int pre) { if (node == null) { return new int[]{0, 0}; } int[] left = dfs(node.left, node.val); int[] right = dfs(node.right, node.val); int[] cur = new int[]{1, 1}; if (node.val == pre + 1) { cur[0] = Math.max(cur[0], left[0] + 1); cur[1] = Math.max(cur[1], right[1] + 1); } else if (node.val == pre - 1) { cur[0] = Math.max(cur[0], right[0] + 1); cur[1] = Math.max(cur[1], left[1] + 1); } return cur; } } ``` 其 dfs 函数返回一个长度为 2 的数组,第一个元素表示以当前结点为结尾的 LIS 长度,第二个元素表示以当前结点为结尾的 LDS 长度。对于每个结点,我们分别计算其向左子树和右子树的 LIS 和 LDS 长度,并根据当前结点与上一个结点的大小关系来更新当前结点的 LIS 和 LDS 长度。最终返回根节点的 LIS 和 LDS 长度的最大值即可。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值