不给自己任何借口
今日题目:
❤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