文章目录
利用数据结构-栈,队列, 加上相应思路等完成。
2019-06-09 补充 二叉树 不使用栈 进行 先序/中序 非递归遍历(摘自leetcode上某个大神)视频讲解:https://www.youtube.com/watch?v=wGXB9OWhPTg,即Morris 遍历
leetcode题目地址
leetcode练习,隔段时间敲几次代码
144 . Binary Tree Preorder Traversal
https://leetcode.com/problems/binary-tree-preorder-traversal/
https://leetcode-cn.com/problems/binary-tree-preorder-traversal/
94 . Binary Tree Inorder Traversal
https://leetcode.com/problems/binary-tree-inorder-traversal/
https://leetcode-cn.com/problems/binary-tree-inorder-traversal/
145 . Binary Tree Postorder Traversal
https://leetcode.com/problems/binary-tree-postorder-traversal/
https://leetcode-cn.com/problems/binary-tree-postorder-traversal/
非递归先/前序(根-左-右)
非递归,使用栈
利用栈,根节点先pop, 然后先push right节点,再push left节点,pop则是先左再右
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> ans = new ArrayList<>();
if(root == null){
return ans;
}
Stack<TreeNode> sta = new Stack();
sta.push(root);
while(!sta.isEmpty()){
TreeNode node = sta.pop();
ans.add(node.val);
if(node.right != null){
sta.push(node.right);
}
if(node.left != null){
sta.push(node.left);
}
}
return ans;
}
}
非递归,不使用栈
主要是链接前序节点到根,每个根访问两次:一次打印并建立链接,一次是取消链接转向右子树
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> preOrderList = new ArrayList<>(512);
TreeNode current = root;
while(current != null) {
// 左子树是null, 则 打印该节点,转向该节点的右子树
if (current.left == null) {
preOrderList.add(current.val);
current = current.right; // 靠right 设置current
}else {
// find the predecessor(该节点的左子树 的 最右节点,不能等于该节点)
TreeNode predecessor = current.left;
while(predecessor.right != current && predecessor.right != null) {
predecessor = predecessor.right;
}
// 该节点第一次遍历 建立 predecessor.right = 自己
if(predecessor.right == null) {
preOrderList.add(current.val);
predecessor.right = current;
current = current.left;
}else { // 该节点第二次被访问到, predecessor.right不是null,是自己了,并消除这种link
predecessor.right = null;
current = current.right;
}
}
}
return preOrderList;
}
}
非递归中序(左-根-右)
非递归,使用栈
每次取栈顶,而栈的顺序是 从根到最左,取出该节点打印并出栈
如果取出的节点没有右子树
则cur = cur->right;为null,下一次取出其父节点
如果右子树不为空
则 cur = cur->right;后下一次会往栈中添加右子树,但是根是在这之前入栈的
即操作确保了一定是 左 根 右 的顺序
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> ans = new ArrayList<>();
if(root == null){
return ans;
}
Stack<TreeNode> sta = new Stack<>();
TreeNode cur = root;
while(!sta.isEmpty() || cur != null){
if(cur != null){ // 不断的左,直到左节点为空
sta.push(cur);
cur = cur.left;
}else{
TreeNode node = sta.pop();
ans.add(node.val);
if(node.right == null){
// do nothing; 即继续弹出栈中元素
}else{
// 左子树为空,根打印了,那么转向右子树
cur = node.right;
}
}
}
return ans;
}
}
非递归,不使用栈
主要是链接前序节点到根,每个根访问两次:第一次建立链接,另一次是取消链接 并打印,即后打印根,然后在转向右子树
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> ans = new ArrayList(16);
if(root == null){
return ans;
}
TreeNode cur = root;
while(cur != null){
if(cur.left == null){
ans.add(cur.val);
cur = cur.right; // 右子树建立遍历关联
}else{
// 不断的找到最右节点
TreeNode pre = cur.left;
while(pre.right != null && pre.right != cur){
pre = pre.right;
}
if(pre.right == null){ // 第一次访问
pre.right = cur;
cur = cur.left;
}else{ // 第二次访问
ans.add(cur.val);
pre.right = null;
cur = cur.right;
}
}
}
return ans;
}
}
非递归后序(左-右-根)
非递归,使用栈
需要记录是否右子树访问完成,然后再访问根(对比下中序非递归使用栈)
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> ans = new ArrayList<>();
if(root == null){
return ans;
}
TreeNode preVisit = null;
TreeNode cur = root;
Stack<TreeNode> sta = new Stack();
while(!sta.isEmpty() || cur != null){
if(cur != null){
sta.push(cur);
cur = cur.left;
}else{
TreeNode node = sta.peek();
if(node.right == null || node.right == preVisit){
sta.pop();
ans.add(node.val);
preVisit = node;
}else{
cur = node.right;
}
}
}
return ans;
}
}
非递归,不使用栈
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> preOrderList = new ArrayList<>(512);
TreeNode current = root;
while(current != null) {
if (current.left == null) {
current = current.right;
}else {
TreeNode predecessor = current.left;
while(predecessor.right != current && predecessor.right != null) {
predecessor = predecessor.right;
}
if(predecessor.right == null) {
predecessor.right = current;
current = current.left;
}else {
// 先消除链接
predecessor.right = null;
// current.left 右子树靠right链接起来了,需要逆序全部访问到
addPath(preOrderList, current.left);
current = current.right;// 继续转向右子树,如果为空则退出
}
}
}
// 前面操作确保了,左子树先全部完成了,然后右子树的左子树也全部完成了,且右子树的右节点为null
// 那么只需要再来一次逆序访问即可
addPath(preOrderList, root);
return preOrderList;
}
public void addPath(List<Integer> res, TreeNode node) {
// 添加元素
int count = 0;
while (node != null) {
++count;
res.add(node.val);
node = node.right;
}
// 逆序
int left = res.size() - count;
int right = res.size() - 1;
while (left < right) {
int temp = res.get(left);
res.set(left, res.get(right));
res.set(right, temp);
left++;
right--;
}
}
}
使用二叉树非递归遍历的一些题目
230. Kth Smallest Element in a BST
题目地址
https://leetcode.com/problems/kth-smallest-element-in-a-bst/
ac代码如下;
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
int kthSmallest(TreeNode* root, int k) {
if (root == NULL)
return 0;
stack<TreeNode*> sta;
sta.push(root);
TreeNode* pLeft = root->left;
int outTh = 1;
while (!sta.empty() || pLeft != NULL)
{
while (pLeft != NULL)
{
sta.push(pLeft);
pLeft = pLeft->left;
}
TreeNode* top = sta.top();
sta.pop();
if (outTh == k)
{
return top->val;
}
outTh++;
//cout << top->val;
if (top->right != NULL)
pLeft = top->right;
}
return 0;
}
};
114. Flatten Binary Tree to Linked List
题目地址
https://leetcode.com/problems/flatten-binary-tree-to-linked-list/
题目描述
Given a binary tree, flatten it to a linked list in-place.
For example,
Given
1
/ \
2 5
/ \ \
3 4 6
The flattened tree should look like:
1
\
2
\
3
\
4
\
5
\
6
采用非递归,使用堆栈的先序遍历
ac代码如下:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
void flatten(TreeNode* root) {
if (root == NULL)
return;
stack<TreeNode*> sta;
sta.push(root);
TreeNode* lastNode = NULL;
while (!sta.empty())
{
TreeNode* top = sta.top();
sta.pop();
if (top->right != NULL)
sta.push(top->right);
if (top->left != NULL)
sta.push(top->left);
if (lastNode != NULL){
lastNode->left = NULL;
lastNode->right = top;
}
lastNode = top;
}
return;
}
};
采用递归
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
void dfs(TreeNode* root)
{
if (root == NULL)
return;
else if (root->left == NULL && root->right == NULL)
return;
else if (root->left != NULL && root->right == NULL){
TreeNode* rootL = root->left;
dfs(rootL);
root->left = NULL;
root->right = rootL;
return;
}
else if (root->left == NULL && root->right != NULL)
{
TreeNode* rootR = root->right;
dfs(rootR);
root->right = rootR;
return ;
}
else{
TreeNode* rootL = root->left;
TreeNode* rootR = root->right;
dfs(rootL);
dfs(rootR);
root->right = rootL;
root->left = NULL;
TreeNode* pre = NULL;
TreeNode* t = rootL;
while (t != NULL){
pre = t;
t = t->right;
}
pre->right = rootR;
}
}
void flatten(TreeNode* root) {
if (root == NULL)
return;
dfs(root);
return;
}
};
采用非递归,不使用栈
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public void flatten(TreeNode root) {
if(root == null){
return;
}
TreeNode cur = root;
while(cur != null){
if(cur.left == null){
cur = cur.right;
}else{
TreeNode preNode = cur.left;
while(preNode.right != null){
preNode = preNode.right;
}
// cur.right变成preNode的右子树
TreeNode curRight = cur.right;
cur.right = null;
preNode.right = curRight;
// 左子树变右子树,顺便就把cur.left设置成right了
TreeNode curLeft = cur.left;
cur.left = null;
cur.right = curLeft;
cur = cur.right;
}
}
}
}
面试题 17.12. BiNode
https://leetcode-cn.com/problems/binode-lcci/
非递归使用栈
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public TreeNode convertBiNode(TreeNode root) {
if(root == null){
return null;
}
Stack<TreeNode> sta = new Stack<>();
TreeNode dummy = new TreeNode(-1);
TreeNode tail = dummy;
TreeNode cur = root;
while(!sta.isEmpty() || cur != null){
if(cur != null){
sta.push(cur);
cur = cur.left;
}else{
TreeNode node = sta.pop();
if(node.right != null){
cur = node.right;
}
tail.right = node;
tail = node;
tail.left = null;
}
}
TreeNode res = dummy.right;
dummy.right = null;
return res;
}
}
非递归,不使用栈
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public TreeNode convertBiNode(TreeNode root) {
if(root == null){
return null;
}
TreeNode dummy = new TreeNode(-1);
TreeNode tail = dummy;
TreeNode cur = root;
while(cur != null){
if(cur.left == null){
TreeNode node = cur;
cur = cur.right;
tail.right = node;
tail = node;
tail.left = null;
}else{
TreeNode pre = cur.left;
while(pre.right != null && pre.right != cur){
pre = pre.right;
}
// 第一次访问
if(pre.right == null){
pre.right = cur;
cur = cur.left;
}else{
pre.right = null;
TreeNode node = cur;
// 转向右子树
cur = cur.right;
tail.right = node;
tail = node;
tail.left = null;
}
}
}
TreeNode res = dummy.right;
dummy.right = null;
return res;
}
}