C++牛客网编程(十一)

目录

找到两个无环单向链表的第一个公共点

二叉搜索树转换成双向链表

判断是否是平衡二叉树


找到两个无环单向链表的第一个公共点

描述

输入两个无环的单向链表,找出它们的第一个公共结点,如果没有公共节点则返回空。(注意因为传入数据是链表,所以错误测试数据的提示是用其他方式显示的,保证传入数据是正确的)

数据范围: n≤1000n
要求:空间复杂度 O(1),时间复杂度 O(n)

例如,输入{1,2,3},{4,5},{6,7}时,两个无环的单向链表的结构如下图所示:

可以看到它们的第一个公共结点的结点值为6,所以返回结点值为6的结点。

思路:先计算出两个链表的长度,计算差值。长链表遍历结点先向后移动差值个结点,再和短链表一起向后遍历,直到两个遍历结点的地址相同。

class Solution {
public:
    ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {
        int l1=0,l2=0,a=0;//l1代表pHead1的长度,l2代表pHead2的长度,a代表长度差值
        ListNode* p1=pHead1;
        ListNode* p2=pHead2;
        if(p1==NULL||p2==NULL) return NULL;//有一个为空
        while(p1!=NULL){//计算p1链表长度
            l1++;
            p1=p1->next;
        }
        while(p2!=NULL){//计算p2链表长度
            l2++;
            p2=p2->next;
        }
        p1=pHead1;
        p2=pHead2;
        if(l1>l2){//如果l1大,则移动链表pHead1
            a=l1-l2;
            while(a>0){
                p1=p1->next;
                a--;
            } 
        }
        else if(l1<l2){//如果l2大,则移动链表pHead2
            a=l2-l1;
            while(a>0){
                p2=p2->next;
                a--;
            } 
        }
        while(p1!=NULL&&p2!=NULL&&p1!=p2){//一起向后移动
            p1=p1->next;
            p2=p2->next;
        }
        if(p1==NULL||p2==NULL) return NULL;//没有公共节点
        return p1;
    }

二叉搜索树转换成双向链表

描述

输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。如下图所示

数据范围:输入二叉树的节点数 0≤n≤10000 ,二叉树中每个节点的值 0≤val≤10000
要求:空间复杂度O(1)(即在原树上操作),时间复杂度 O(n)

注意:

1.要求不能创建任何新的结点,只能调整树中结点指针的指向。当转化完成以后,树中节点的左指针需要指向前驱,树中节点的右指针需要指向后继
2.返回链表中的第一个节点的指针
3.函数返回的TreeNode,有左右指针,其实可以看成一个双向链表的数据结构

4.你不用输出双向链表,程序会根据你的返回值自动打印输出

 思路:利用中序遍历递归,找到每个结点的中序序列中的前结点和后结点作为左右结点。但在实际代码中,可只找到前序结点,即可完成前后结点的连接工作。

class Solution {
public:
    TreeNode* pre=NULL;
    void first(TreeNode* root){
        if(!root) return;
        first(root->left);//找到中序遍历中根结点的前序结点
        root->left=pre;
        if(pre) pre->right=root;
        pre=root;//根结点作为右子树中序遍历第一个的前序结点
        first(root->right);
    }
    TreeNode* Convert(TreeNode* pRootOfTree) {
        if(!pRootOfTree) return NULL;
        TreeNode* p=pRootOfTree;
        while(p->left) p=p->left;//找到双向链表的第一个结点
        first(pRootOfTree);
        return p;
    }
};

重点:一开始执着于找到左右结点,并分别进行双向连接,没有考虑到两个结点的前后关系就可以扩展到整个链表了。

判断是否是平衡二叉树

描述

输入一棵节点数为 n 二叉树,判断该二叉树是否是平衡二叉树。

在这里,我们只需要考虑其平衡性,不需要考虑其是不是排序二叉树

平衡二叉树(Balanced Binary Tree),具有以下性质:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。

样例解释:

样例二叉树如图,为一颗平衡二叉树

注:我们约定空树是平衡二叉树。

数据范围:n≤100n,树上节点的val值满足 0≤n≤10000

要求:空间复杂度O(1),时间复杂度 O(n)

思路:分为自顶向下和自底向上两种方法。第一个从根结点着手,如果左子树和右子树之差大于1就不是平衡树,但递归是从下往上,所以需要额外的空间存储每个点的左右子树差,不满足题意。第二个是从叶子结点开始向上,通过改编求结点高度的递归函数可以得到。

class Solution {
public:
    int high(TreeNode* root){
        if(!root) return 0;
        int l=high(root->left);
        if(l==-1) return -1;//如果左子树不是平衡树
        int r=high(root->right);
        if(r==-1) return -1;//如果右子树不是平衡树
        if(abs(l-r)>1) return -1;//如果不是平衡树
        return max(l,r)+1;
    }
    bool IsBalanced_Solution(TreeNode* pRoot) {
        return high(pRoot)!=-1;
    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值