230. Kth Smallest Element in a BST

不要被题目迷惑,肯定是要O(N)的时间,在不改变数据结构的情况下。
就是in-order traverse,因为是BST,所以遍历顺序是从小到大,遍历的第K个元素就是第K小的。

可以Iteratively,也开始recursively.

public class Solution 
{   
    /* recursion version
    int count = 0;
    int res = 0;
    public int kthSmallest(TreeNode root, int k) 
    {
        
        helper(root,k);
        return res;
        
    }
    
    public void helper(TreeNode root, int k)
    {
        
        if(root == null || count == k) return;
        

        
        helper(root.left,k);
        count++;
        if(count == k)
        {
            res = root.val;
            return;
        }
        helper(root.right,k);
    }
    */
    
    public int kthSmallest(TreeNode root, int k)
    {
        int res = 0;
        int count = 0;
        
        Stack<TreeNode> stk = new Stack<TreeNode>();
        
        TreeNode temp = root;
        while(temp != null || !stk.isEmpty())
        {
            while(temp!=null)
            {
                stk.push(temp);
                temp = temp.left;
            }
            temp = stk.pop();
            count++;
            if(count == k)
            {
                res = temp.val;
                break;
            }
            if(count>=k)break;
            temp = temp.right;
        }
        
        return res;
    }
    
}

至于follow up,无非是如何提供信息,让每次左还是右能做出选择。Node的结构里直接加1个数表示第几小的,这样遍历就知道往左还是往右了。




二刷

又一次被follow up给迷惑了,以为有O(height)的做法,感觉要被刷新三观,实际上是没有的。

利用in-order是sorted的特性按部就班地做就行了。

Iterative:

public class Solution {
    public int kthSmallest(TreeNode root, int k) {
        Stack<TreeNode> stk = new Stack<>();
        TreeNode temp = root;
        while (!stk.isEmpty() || temp != null) {
            while (temp != null) {
                stk.push(temp);
                temp = temp.left;
            }
            temp = stk.pop();
            if (--k == 0) {
                return temp.val;
            }
            temp = temp.right;
        }
        
        return -1;
    }
}

Recursive:

public class Solution {
    int res;
    int count = 0;
    public int kthSmallest(TreeNode root, int k) {
        dfs(root, k);   
        return res;    
    }
    
    public void dfs(TreeNode root, int k) {
        if (root == null) return;
        dfs(root.left, k);
        if (++count == k) {
            res = root.val;
            return;
        }
        dfs(root.right, k);
    }
}

2个办法都很基础。。

看了一下Discussion,剽窃到一个用二分的方法,实际情况会比较快。
作者的名字真忘了,光记得他给了3种方法,剩下2种就是上面的2种,他说STACK那个是BFS,其实不是,是DFS。。。

Binary-Search
做到一半觉得不对,这他妈是TOP-DOWN啊,快个鸡巴。。最坏的情况是O(n^2)。。

public class Solution {

    public int kthSmallest(TreeNode root, int k) {

        int left = getNum(root.left);  
        if (left + 1 < k) {
            return kthSmallest(root.right, k - left - 1);
        } else if (left + 1 > k) {
            return kthSmallest(root.left, k);
        } else {
            return root.val;
        }
    }
    
    public int getNum(TreeNode root) {
        if (root == null) return 0;
        return getNum(root.left) + getNum(root.right) + 1;
    }
    
    
}

但是实际binary search这个方法的思路就是题目中follow-up的思路。
二分的时候,我们先算左边,如果左边总数比K小,我们直接去右边找就行了;如果总数比K大,就要去左边重新计算数量,很麻烦,但是如果提前改变结构,每个Node都知道左支有多少个,就不用每次都找了,可以直接判断。

follow-up的答案就是先preprocess the entire tree...这样除了一开始的过程是O(n),用post-order,后来一直是O(Height)

posted @ 2016-11-26 05:50  哇呀呀..生气啦~  阅读(114)  评论(0编辑  收藏  举报