leetcode题解日练--2016.8.6

来源:互联网 发布:王者荣耀淘宝充值点卷 编辑:程序博客网 时间:2024/05/09 19:57

不给自己任何借口

今日题目:

❤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
原创粉丝点击