🤞目录🤞
💖1. 按之字形顺序打印二叉树
💖2. 二叉搜索树的第k个节点
💖3. 二叉搜索树的第k大节点
【大家好,我是爱干饭的猿,如果喜欢这篇文章,点个赞👍,关注一下吧,后续会一直分享题目与算法思路】
🚠1. 按之字形顺序打印二叉树
描述
?给定一个二叉树,返回该二叉树的之字形层序遍历,(第一层从左向右,下一层从右向左,一直这样交替)
例如: 给定的二叉树是{1,2,3,#,#,4,5}
该二叉树之字形层序遍历的结果是
[
[1],
[3,2],
[4,5]
]
解题思路:
🎈思路一:本质也是对树形结构的层序遍历,不过在遍历的过程中,需要更改遍历顺序
我们可以采用queue的方式来进行处理
核心思路:不论当前层从左向右遍历还是从右向左遍历,都是下层就从left到right入队并且list.add(元素),只是当前层如果从右向左遍历,将list集合元素逆置即可(详见代码)
🎈思路二: 我们可以也采用stack和queue的方式来进行处理
核心思路:当前层从左向右遍历,那么下层就从left到right入栈,当前层如果从右向左遍历,那么下层就从right到 left入栈(详见代码)
🌅思路一:代码如下:
// 方法一:
public ArrayList<ArrayList<Integer>> Print(TreeNode pRoot) {
if(pRoot == null){
return new ArrayList<>();
}
ArrayList<ArrayList<Integer>> result = new ArrayList<>();
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(pRoot);
// 1 表示正序 ,2 表示逆序
// 先默认flag为2 ,进入while时 保证第一次是正序
int flag = 2;
while (!queue.isEmpty()){
ArrayList<Integer> list = new ArrayList<>();
ArrayList<Integer> reList = new ArrayList<>();
int size = queue.size();
flag = flag == 2 ? 1 : 2;
for (int i = 0; i < size; i++) {
TreeNode cur = queue.poll();
if(flag == 1){
list.add(cur.val);
}else {
reList.add(cur.val);
}
if(cur.left != null) queue.offer(cur.left);
if(cur.right != null) queue.offer(cur.right);
}
// 将该层数逆置存入list
for (int i = reList.size()-1; i >= 0 ; i--) {
list.add(reList.get(i));
}
result.add(list);
}
return result;
}
🌅思路二:代码如下:
// 方法二:
public ArrayList<ArrayList<Integer>> Print2(TreeNode pRoot) {
ArrayList<ArrayList<Integer>> result = new ArrayList<>();
if (pRoot == null) {
return result;
}
Stack<TreeNode> st = new Stack<>();
Queue<TreeNode> q = new LinkedList<>(); //临时区域
st.push(pRoot);
int dir = 1;
//1:代表left->right式入栈. 2: 代表right->left式入栈
ArrayList<Integer> list = new ArrayList<>();//保存一层结果的临时变量
while (!st.empty()) {
int size = st.size();
//清空本层所有节点,将下层节点按照要求入栈,栈具有天然的逆序的能力
for (int i = 0; i < size; i++) {
TreeNode curr = st.pop();
list.add(curr.val);
TreeNode first = (dir == 1) ? curr.left : curr.right;
TreeNode second = (dir == 1) ? curr.right : curr.left;
if (first != null) q.offer(first);
if (second != null) q.offer(second);
}
//本层遍历完毕,入结果集
result.add(new ArrayList(list));
//一定要注意浅拷贝问题
list.clear();
//将所有节点入栈,进行逆序
while (!q.isEmpty()) {
st.push(q.poll());
}
dir = (dir == 1) ? 2 : 1;
}
return result;
}
🚠2. 二叉搜索树的第k个节点
描述
给定一棵结点数为n 二叉搜索树,请找出其中的第 k 小的TreeNode结点值。
1.返回第k小的节点值即可
2.不能查找的情况,如二叉树为空,则返回-1,或者k大于n等等,也返回-1
3.保证n个节点的值不一样
例如:
输入{5,3,7,2,4,6,8},3时,二叉树{5,3,7,2,4,6,8}如下图所示:
?该二叉树所有节点按结点值升序排列后可得[2,3,4,5,6,7,8],所以第3个结点的结点值为4,故返回对应结点值为4的结点即可。
解题思路:
🎈思路一:BST本身就是有序的,中序遍历即是升序
要求第k小,即中序遍历时到达第k个元素(二叉搜索树,不存在两个相同的节点值)
此处,我们不使用递归,我们采用循环中序遍历的方式(详见代码)
?🌅思路一:代码如下:
public int KthNode (TreeNode proot, int k) {
if(proot == null || k <= 0){
return -1;
}
Stack<TreeNode> stack = new Stack<>();
TreeNode cur = proot;
while (cur != null || !stack.isEmpty()){
// 层序遍历,先走到最小值(最左)
while (cur != null){
stack.push(cur);
cur = cur.left;
}
if(!stack.isEmpty()){
// 出栈k次
cur = stack.pop();
k--;
if(k == 0){
return cur.val;
}
}
cur = cur.right;
}
return -1;
}
🚠3. 二叉搜索树的第k大节点
描述
给定一棵二叉搜索树,请找出其中第?k ?大的节点的值。?
例如:
解题思路:
🎈思路一:和上一题几乎一模一样,
只是现在要求第k大,即中序遍历变式(右根左)时到达第k个元素(二叉搜索树,不存在两个相同的节点值) (详见代码)
?🌅思路一:代码如下:
public int kthLargest(TreeNode root, int k) {
if(root == null || k <= 0){
return 0;
}
Stack<TreeNode> stack = new Stack<>();
TreeNode cur = root;
while (!stack.isEmpty() || cur != null){
// 层序遍历变式(右根左),先走到最大值(最右)
while (cur != null){
stack.push(cur);
cur = cur.right;
}
if(!stack.isEmpty()){
// 出栈k次
cur = stack.pop();
k -- ;
if(k == 0){
return cur.val;
}
}
cur = cur.left;
}
return 0;
}
|