题目:
2) Write code to find the 2nd smallest element in a binary search tree (BST) .
Java class Node { public Node left; public Node right; public Node parent; public int value; } |
C++ class Node { public: Node *left; Node *right; Node *parent; int value; } |
Python class Node: self.parent=None |
解决方案:
首先确认了是BST,所以所有的数据是排序的,第一思路是做一个中序扫描(先左再根后右),然后读取第二个元素。当时电话里也仅仅做到了这一步没有继续下去,但是也给了我机会去面试。现在有时间,想到的一个优化算法是,在做排序的过程中,一旦找到了第二小的元素,便跳出扫描,跳出递归的方式用流行的自定义RuntimeException的方式,代码如下:
public class TMC { @SuppressWarnings("serial") static class StopRecursorException extends RuntimeException { } private int secNum; public int getSec(TMCNode root) { secNum = Integer.MIN_VALUE; try { int count = 0; count = midTravel(root, count); return secNum; // nodes less than 2 } catch (StopRecursorException e) { return secNum; } } public int midTravel(TMCNode root, int count) { if (root != null) { midTravel(root.left, count); ++count; if (count == 2) { // second smallest secNum = root.value; throw new StopRecursorException(); } midTravel(root.right, count); } return count; } } class TMCNode { public TMCNode left; public TMCNode right; public TMCNode parent; public int value; public TMCNode(TMCNode left, TMCNode right, TMCNode parent, int value) { this.left = left; this.right = right; this.parent = parent; this.value = value; } }
我相信我现在给出的方法还不是面试官所期待的最优算法,这个node的设置里面有parent,这个父节点我根本没有用到。
关于这个问题有个详尽版本在http://www.geeksforgeeks.org/find-k-th-smallest-element-in-bst-order-statistics-in-bst
还有诸多讨论在http://stackoverflow.com/questions/2329171/find-kth-smallest-element-in-a-binary-search-tree-in-optimum-way
update:
在查询改问题的时候,有个回复提到了,找到最小值以后,再找一次最小值就是第二小的数,所以当问题是确定了第二小的时候,有这样的解法:
public int find2ndSmallest(TMCNode node) { TMCNode currentNode = node; // here also a bug, need check if root is null or not while (currentNode.left != null) { currentNode = currentNode.left; } // after this loop, we reach the smallest (left end) if (currentNode.right == null) { // no child, parent is second smallest return currentNode.parent.value; // here is a bug, if root need return less than 2 nodes } else { // right child currentNode = currentNode.right; while (currentNode.left != null) { currentNode = currentNode.left; } // find smallest in right child tree return currentNode.value; } }
做出这个解法的时候我想起了当初在LCM(Shanghai)面试的时候,马博士给我的一个比赛冠军题,然后问道亚军如何计算。1对1的比赛其实就是二叉树,确定冠军的时候,找亚军又是一个可以简化的问题。
发现自己还有很多题可以啃。