給定一棵二叉搜索樹,請找出其中的第k小的結點。java
一開始我沒有注意到二叉搜索樹這個詞,我仍是覺得是一個普通的二叉樹,因此我就按照個人想法,將二叉樹的節點放入到一個數組中。node
因爲一開始我沒有注意到二叉搜索樹這個概念,因此的個人思路是按照普通二叉樹的查找進行的,具體思路以下所示:算法
moveArr
moveArr
函數中定義了將節點按照直接插入排序的思想進行排序。當我完成個人算法而且經過的時候,我再一次查看題解時發現,我仍是粗心了,並無發現題目中所給出的隱含的意思。二叉搜索樹是一個很是特別的二叉樹,當一個節點的左子樹和右子樹都存在時,左子樹中的值都小於該節點,右子樹中的全部值都大於該節點。
二叉搜索樹的中序遍歷就是一個升序排序的數組,因此查找第k小的節點,就查找數組中索引爲k-1的節點便可。
可是中序遍歷是找到全部的節點,可是咱們只須要找到第k小的節點便可,因此咱們對算法有了一些改進,使用非遞歸的中序遍歷,找到第k小的節點就跳出循環。數組
具體的思路:函數
樹節點的函數:this
public class TreeNode { int val = 0; TreeNode left = null; TreeNode right = null; public TreeNode(int val) { this.val = val; }
TreeNode KthNode(TreeNode pRoot, int k) { if(pRoot == null || k < 1) return null; // 看到這個問題,我首先想到的方法是,將樹放入到一個數組中,而後將數組進行判斷,返現最小的數值 // 首先新建一個k位大小的數組,而後依次遍歷二叉樹,將數值插入到該數組中 TreeNode[] arr = new TreeNode[k]; addTreeNode(pRoot, arr); return arr[k-1]; } // 遍歷將數節點加入到數組中 public void addTreeNode(TreeNode node, TreeNode[] arr){ if(node == null) return; moveArr(node, arr); if(node.left != null) addTreeNode(node.left, arr); if(node.right != null) addTreeNode(node.right, arr); } // 數組移位, 判斷數組要比哪個小 public void moveArr(TreeNode node, TreeNode[] arr){ if(node == null) return; for(int i=0; i<arr.length; i++){ if(arr[i] == null){ arr[i] = node; return; }else if(node.val < arr[i].val){ for(int j = arr.length-1; j > i; j--){ arr[j] = arr[j-1]; } arr[i] = node; return; } } }
TreeNode KthNode(TreeNode pRoot, int k){ // 一開始沒有仔細的看待問題,若是仔細的看問題以及對二叉樹很是熟悉的話,應該第一時間就注意到了 二叉搜索樹 這個詞語 // ,二叉搜索樹中一個節點的左子樹中的值應該小於該節點,右子樹中的值都應該大於該節點 if(pRoot == null || k < 1) return null; // 二叉樹的中序遍歷就能夠找到該節點的排序,只要找到第k個元素就能夠找到問題中所要找的節點 // 非遞歸的方法須要使用Stack來存儲父節點 TreeNode node = pRoot; Stack<TreeNode> stack = new Stack<>(); int count = 0; while(node != null || !stack.isEmpty()){ if(node != null){ stack.push(node); node = node.left; }else{ node = stack.pop(); count ++; if(count == k) return node; node = node.right; } } return null; }