Skip to main content

Morris PostOrder Traversal of a Binary Tree

Problem Statement:​

  • Example:





✅ Solution: Morris Postorder Traversal​

class Solution {
public:
// Helper to reverse the path and collect values
void reversePath(TreeNode* startNode, TreeNode* endNode, vector<int>& result) {
reverseEdges(startNode, endNode);

TreeNode* node = endNode;
while (true) {
result.push_back(node->val);
if (node == startNode) break;
node = node->right;
}

reverseEdges(endNode, startNode); // Restore original tree structure
}

// Reverses right pointers between two nodes
void reverseEdges(TreeNode* fromNode, TreeNode* toNode) {
if (fromNode == toNode) return;
TreeNode* prev = fromNode;
TreeNode* curr = fromNode->right;
TreeNode* next;

while (prev != toNode) {
next = curr->right;
curr->right = prev;
prev = curr;
curr = next;
}
}

vector<int> postorderTraversal(TreeNode* root) {
vector<int> postorderResult;
TreeNode dummy(0); // Dummy node simplifies edge handling
dummy.left = root;
TreeNode* current = &dummy;

while (current != NULL) {
if (current->left == NULL) {
current = current->right;
} else {
TreeNode* predecessor = current->left;
while (predecessor->right && predecessor->right != current) {
predecessor = predecessor->right;
}

if (predecessor->right == NULL) {
// Make thread and move left
predecessor->right = current;
current = current->left;
} else {
// Visit in reverse and remove thread
reversePath(current->left, predecessor, postorderResult);
predecessor->right = NULL;
current = current->right;
}
}
}

return postorderResult;
}
};


📝 How It Works​

  • This is Morris traversal adapted for postorder, achieving O(1) space.
  • We use a dummy node that links to root to help in final reversal.
  • It works by building temporary threads (right pointers) and reverses the path from left child to predecessor, collects values in reverse, and then restores the structure.

🧩 Key Idea / Trick​

  • For any node, if it has a left child:
    • Find its rightmost predecessor in the left subtree.
    • Create a temporary thread to the current node.
    • After processing left subtree, reverse the path from child to predecessor and collect it.
  • Postorder = Left → Right → Root, so we reverse the order before collecting.

⏱️ Time & Space Complexity​

MetricValue
TimeO(N)
SpaceO(1)
  • No recursion or stack used.
  • Nodes are visited a finite number of times via threaded connections.

⚠️ Edge Cases​

  • Empty tree (returns empty list)
  • Tree with only root node (returns one value)
  • Deep skewed tree (still works in O(1) space)

💡 Other Approaches​

ApproachTimeSpaceRemarks
Recursive DFSO(N)O(H)Uses call stack
Iterative + StackO(N)O(H)Clean and easy to understand
✅ Morris TraversalO(N)O(1)Optimal space, trickier logic

  • Leetcode 145. Binary Tree Postorder Traversal
  • Leetcode 94. Inorder Traversal
  • Leetcode 144. Preorder Traversal
  • Leetcode 199. Binary Tree Right Side View

🚀 Level Up Your Engineering Mindset

Never Study in Isolation. Join Binary Dose.

Connect with fellow engineers, clear conceptual doubts, and get 2 visual breakdowns & engineering mental models daily across our community channels.

Discord
Official Hub

Discord Community

Start at #welcome-and-rules, say hello in #general-chat, clear doubts, and collaborate with engineers worldwide.

Join Discord Server→
⚡
Daily Knowledge Drops

Daily Visual Deep-Dives

Bite-sized system design schematics, core OS internals, and DSA intuition served right into your feeds every single day.

💡Have handwritten notes, cheat-sheets, or want to publish a technical article?
Learn How to Contribute→