剑指offer-找到两个叶子节点的最低公共节点,数组的逆序对的个数,第一个公共链表节点

Posted void-lambda

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了剑指offer-找到两个叶子节点的最低公共节点,数组的逆序对的个数,第一个公共链表节点相关的知识,希望对你有一定的参考价值。

找到两个叶子节点的最低公共节点

思路:

1.若这棵树为二叉搜索树的话,根据特性,我们从根节点遍历,若两个叶子节点值都小于根节点值,则最低公共节点一定在左子树,都大于的话在右子树。当一个小于一个大于时,所到达的节点就是最低公共节点。
2.若这棵树有父指针,那么问题可以转化为求链表的第一个公共节点的问题。
3.若只是棵普通的二叉树,可以两次遍历树,找到根节点到叶子节点的路径并保存。再从路径中比较找出最后一个相同的节点。

代码:

list<TreeNode*> path;
bool GetNodePath(TreeNode* root, TreeNode* pNode, list<TreeNode*>& path)//找到根到所求节点的路径。
{
    if (root == NULL)
        return true;
    path.push_back(root);
    bool found = false;
    if(!found)
    {
        found = GetNodePath(root->left, pNode, path);

    }
    if (!found)
    {
        found = GetNodePath(root->right, pNode, path);
    }
    if (!found)
        path.pop_back();
    return found;
}
TreeNode *GetLastCommonNode(list<TreeNode*> path1,list<TreeNode*> path2)//求两条路径的最后公共节点

{
    
    list< TreeNode*>::iterator it1 = path1.begin();
    list< TreeNode*>::iterator it2 = path2.begin();
    TreeNode* plast = NULL;
    while (it1 != path1.end() && it2 != path2.end())
    {
        if (*it1 == *it2)
            plast = *it1;
        it1++;
        it2++;
    }
    return plast;
}
TreeNode* GetLastCommonParent(TreeNode* root, TreeNode* pNode, TreeNode* qNode)
{
    if (root == NULL || pNode == NULL || qNode == NULL)
        return NULL;
    list<TreeNode*> path1;
    list<TreeNode*> path2;
    bool p=GetNodePath(root, pNode, path1);
    bool q=GetNodePath(root, qNode, path2);
    if (p && q)
    {
        return GetLastCommonNode(path1, path2);
    }
    return NULL;
}

数组的逆序对的个数

思路:

采用归并排序的思想,每次归并时用两个指针指向两个数组,比较大小,出现逆序对就将计数器+1.

代码:

void Merge(int arr[], int l, int mid, int r, int *cnt)  //合并两个数组
{
    
    int* help = new int[r - l + 1];  //辅助数组
    int p1 = l;
    int p2 = mid + 1;
    int index = 0;
    while (p1 <= mid && p2 <= r)
    {
        help[index++] = arr[p1] < arr[p2] ? arr[p1] : arr[p2];
        if (arr[p1] > arr[p2])
        {
            (*cnt)+=mid-p1+1; //arr[p1]>arr[p2]时,因为p1后面到mid的数字递增,所以都是逆序的.
            for (int i = p1; i <= mid; i++)
            {
                cout << arr[i] << ' ' << arr[p2] << endl;
            }
            p2++;
            
        }
        else
        {
            p1++;
        }
    }
    while (p1 <= mid)  //复制剩余的元素
    {
        help[index++] = arr[p1++];
        
    }
    while (p2 <= r)
    {
        help[index++] = arr[p2++];
    }
    for (int i = 0; i < r - l + 1; i++) //复制到原数组
    {
        arr[l + i] = help[i];
    }
    delete[] help;
}
void MergeSort(int arr[], int l, int r,int *cnt)
{
    
    if (l == r)
        return;
    if (l < r)
    {
        int mid = (l + r) / 2;
        MergeSort(arr, l, mid,cnt);
        MergeSort(arr, mid + 1,r,cnt);
        Merge(arr, l, mid, r,cnt);
    }
    
}
int FindInversePairs(int arr[], int len)
{
    int cnt = 0;
    if (len <= 0 || arr == NULL)
    {
        return 0;
    }
    MergeSort(arr, 0, len - 1,&cnt);
    return cnt;
}

第一个公共链表节点

思路:

1.从后往前找最后一个公共节点,但是单链表只能向前。最后遍历的节点却要最先访问,所以用两个栈来贮存源节点到尾节点的路径。需要辅助空间。
2.可以先遍历一次链表分别得到长度,让长的链表先走几步,然后一起运动,就可以同时到达公共节点。

代码:

ListNode* FirstCommonListNode(ListNode* head1, ListNode* head2)
{
    if (head1 == NULL || head2 == NULL)
    {
        return NULL;
    }
    int len1 = 0;
    int len2 = 0;
    ListNode* p = head1;
    while (p)
    {
        len1++;
        p = p->next;
    }
    p = head2;
    while (p)
    {
        len2++;
        p = p->next;
    }
    if (len1 > len2)
    {
        for (int i = 0; i < len1 - len2; i++)
        {
            head1 = head1->next;
        }
    }
    else if (len1 < len2)
    {
        for (int i = 0; i < len2 - len1; i++)
        {
            head2 = head2->next;
        }
    }
    ListNode*p1 = head1;
    ListNode* p2 = head2;
    while (p1 && p2)
    {
        if (p1 == p2)
            return p1;
        else
        {
            p1 = p1->next;
            p2 = p2->next;
        }
    }
    return NULL;
}

以上是关于剑指offer-找到两个叶子节点的最低公共节点,数组的逆序对的个数,第一个公共链表节点的主要内容,如果未能解决你的问题,请参考以下文章

剑指Offer对答如流系列 - 树中两个结点的最低公共祖先

寻找二叉树中的最低公共祖先结点----LCA(Lowest Common Ancestor )问题(递归)

剑指 Offer 52. 两个链表的第一个公共节点

《剑指offer》--- 两个链表的第一个公共结点

LeetCode 1877. 数组中最大数对和的最小值/剑指 Offer 52. 两个链表的第一个公共节点/146. LRU 缓存机制

剑指offer 36.时间空间效率的平衡两个链表的第一个公共结点