Open caibirdme opened 4 years ago
Convert Sorted List to Binary Search Tree 把一个有序链表转成平衡二叉搜索树。想想一下,如果我们已经有了这颗BST,那么我们对它进行中序遍历,结果就是题目给的链表。我们可以尝试遍历这颗虚拟的树。回想一下怎么在0..n初始化一颗线段树,同样的做法。只是我们使用中序遍历。
fn in_order(head: &mut Option<Box<ListNode>>, l: usize, r: usize) -> Option<Rc<RefCell<TreeNode>>> {
if l == r {
let node = TreeNode::new(head.as_ref().unwrap().val);
*head = head.take().unwrap().next;
return Some(Rc::new(RefCell::new(node)));
}
let mid = (l+r) / 2;
let lch = {
if mid > l {
Self::in_order(head, l, mid-1)
} else {
None
}
};
let mut root = TreeNode::new(head.as_ref().unwrap().val);
*head = head.take().unwrap().next;
root.left = lch;
root.right = Self::in_order(head, mid+1, r);
Some(Rc::new(RefCell::new(root)))
}
Copy List with Random Pointer 复制单链表很容易,但是由于链表除了next还有个random域,因此复制时需要新建两个节点。并且由于random会随机指向,random可能指向自己,也可能多个random指向同一个节点。因此最直观的办法就是,我们需要建立一个原始链表节点和新链表节点的映射关系。如果random指向的节点已经新建过,就直接指过去。新老关系用hash即可。
还有一种更简便的方式。我们可以把新节点放到原始链表节点的后面,构成这样一个链表。
old1 -> old2 -> old3 -> ...
new1 -> new2-> new3 -> ...
---------
old1 -> new1 -> old2 -> new2 -> ...
之前我们通过hashmap来建立旧节点和新节点的映射关系,而现在,我们直接利用位置来建立映射关系。对于纠结点x,它对应的新节点x'就是x->next。当我们建立完这个链表之后,对于在复制random指针时,x->next->random = x->random->next
这个方法非常巧妙,需要仔细体会。它的启示就是,建立映射处理通过hash直接映射,还可以通过位置进行映射,或者其他方式,可以根据题意来思考。
小节: 链表题目主要还是属于基本功, 基本上不太可能有hard的链表题. 单链表的特点是无法倒序遍历和索引,只能顺序遍历,因此题目大多围绕这两个点展开:
链表的另一类问题就是和环相关:
go over linked-list related problems