leetcode题解日练--2016.8.6

不给自己任何借口

今日题目:

❤1、二叉树最低公共祖先;

2、逆转链表II

今日摘录:

为着后来的回忆,小心着意地描绘你现在的图画

——冰心《冰心散文集》

236. Lowest Common Ancestor of a Binary Tree | Difficulty: Medium

Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree.

According to the definition of LCA on Wikipedia: “The lowest common ancestor is defined between two nodes v and w as the lowest node in T that has both v and w as descendants (where we allow a node to be a descendant of itself).”

        _______3______
       /              \
    ___5__          ___1__
   /      \        /      \
   6      _2       0       8
         /  \
         7   4

For example, the lowest common ancestor (LCA) of nodes 5 and 1 is 3. Another example is LCA of nodes 5 and 4 is 5, since a node can be a descendant of itself according to the LCA definition.

相关题目:Lowest Common Ascestor of a BST
tag:树
题意:找一棵二叉树的两个节点的最低公共祖先。
思路:
1、首先回顾BST情况如何查找LCA?从根节点作为当前判断节点开始,判断当前节点是否同时小于两个待查节点(如果满足说明待LCA在当前节点的右子节点方向),如果同时大于待查找的节点说明LCA在当前节点的左子节点方向,如果均不满足则说明当前节点就是LCA。
但是当时满足了BST这一条件,也就是一个节点的左子节点一定比当前节点小,右子节点一定比当前节点大。但是去掉了这个条件之后我们需要怎么去做呢?还可以用类似的思路,从根节点开始,每次递归去查找我们的待查找节点,每一边第一次遇到任意一个待查找节点就停止继续查找,最后判断根节点的两边是否均有查找到,分情况讨论。
如果左右都找到了,就返回根节点
如果左边找到了而右边没找到,返回左节点,
如果右边找到而左边没找到,返回右节点,
不可能存在左右均没找到的情况

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if (!root || 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 if(left)   return left;
        else    return right;
    }
};

结果:28ms

2、迭代版本,先去找到p和q这两个节点的位置并且记录下来他们的父节点,然后顺着这两条路径去找第一次相关的节点就是LCA。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        stack<TreeNode*> nodes;
        unordered_map<TreeNode*,TreeNode*> parent;
        parent[root] = NULL;
        nodes.push(root);
        while(parent.find(p)==parent.end() || parent.find(q)==parent.end())
        {
            TreeNode* node = nodes.top();
            nodes.pop();
            if(node->left)
            {
                nodes.push(node->left);
                parent[node->left] = node;
            }
            if(node->right)
            {
                nodes.push(node->right);
                parent[node->right] = node;
            }
        }
        set<TreeNode*>path;
        while(p)
        {
            path.insert(p);
            p = parent[p];
        }
        while(q && path.find(q)==path.end())
        {
            path.insert(q);
            q = parent[q];
        }
        return q;
    }
};

结果:64ms

92. Reverse Linked List II | ​Difficulty: Medium

Reverse a linked list from position m to n. Do it in-place and in one-pass.

For example:
Given 1->2->3->4->5->NULL, m = 2 and n = 4,

return 1->4->3->2->5->NULL.

Note:
Given m, n satisfy the following condition:
1 ≤ m ≤ n ≤ length of list.

相关题目:reverse Linked List
tag:链表
题意:反转链表中的一部分

思路:
1、一样的思路,只不过换成了首先找到逆转的头,然后逆转链表,这里面有一个比较关键的点就是是不是从头还是逆转,如果是那么新头是逆转链表的尾部元素,如果不是新头就是原来的头

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* reverseBetween(ListNode* head, int m, int n) {
        int count = n-m+1;
        bool flag;
        if (m==1)  flag = true;
        else     flag = false;
        if(count==1)    return head;
        ListNode* reverseHead = head;
        ListNode* before = head;;
        ListNode * prev = NULL;
        while(--m>0)
        {
            before = reverseHead;
            reverseHead = reverseHead->next;
        }
        ListNode* pNode = reverseHead;
        while(reverseHead && count-->0)
        {
            ListNode*next = reverseHead ->next;
            reverseHead ->next = prev;
            prev = reverseHead;
            reverseHead = next;
        }
        if(!flag)
        {
            before->next = prev;
            pNode->next = reverseHead;
            return head;
        }
        else
        {
         before->next = reverseHead;
         return prev;
        }
    }
};

结果:4ms
第二次刷解法
首先找到反转之后链表的尾部(即reverseHead),它的前面一个是pre,目的是将pre指向反转链表的头部。当我们要逆转(1,3),其实相当于将2指向1,将3指向2,每次reverseHead指向的节点都是当前节点,取出一个当前节点之后就将reverseHead指向当前cur的下一个节点,做n-m次的反转操作之后节点逆序了,pre也指向了反转之后的头部。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* reverseBetween(ListNode* head, int m, int n) {
        if(head==NULL||head->next==NULL||m==n)    return head;
        n-=m;
        ListNode *preHead = new ListNode(0);
        preHead->next = head;
        ListNode*pre = preHead;
        while(--m)  pre = pre->next;
        ListNode* reverseHead = pre->next;
        while(n--)
        {
            ListNode*cur = reverseHead->next;
            reverseHead->next = cur->next;
            cur->next = pre->next;
            pre->next = cur;
        }
        return preHead->next;
    }
};

​结果:4ms

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值