Open In App

Print Postorder traversal from given Inorder and Preorder traversals

Last Updated : 29 Oct, 2024
Comments
Improve
Suggest changes
Like Article
Like
Report

Given two arrays represent Inorder and Preorder traversals of a binary tree, the task is to find the Postorder traversal.

Example:

Input: in[] = [4, 2, 5, 1, 3, 6] pre[] = [1, 2, 4, 5, 3, 6]
Output: 4 5 2 6 3 1
Explanation: Traversals in the above example represents following tree:

print-postorder-traversal-from-given-inorder-and-preorder-traversals

naive method is to first construct the tree, then use a simple recursive method to print postorder traversal of the constructed tree. We can print postorder traversal without constructing the tree.

[Naive approach] Search current element every time - O(n^2) Time and O(n) Space

The idea is that root is always the first item in preorder traversal and it must be the last item in postorder traversal. We first recursively print left subtree, then recursively print right subtree. Finally, print root. 

To find boundaries of left and right subtrees in pre[] and in[], we search root in in[], all elements before root in in[] are elements of left subtree, and all elements after root are elements of right subtree. In pre[], all elements after index of root in in[] are elements of right subtree. And elements before index (including the element at index and excluding the first element) are elements of left subtree.

Below is the implementation of the above approach: 

C++
// C++ program to print postorder traversal 
// from preorder and inorder traversals
#include <iostream>
#include <vector>
using namespace std;

int search(vector<int>& arr, int x) {
    for (int i = 0; i < arr.size(); i++)
        if (arr[i] == x)
            return i;
    return -1;
}

// Prints postorder traversal from given inorder and
// preorder traversals
void printPostOrder(vector<int>& in, vector<int>& pre,
                    int inStart, int inEnd, int preStart) {
    // Base case
    if (inStart > inEnd) return;

    // The first element in pre[] is 
  	// always root
    int rootIndex = search(in, pre[preStart]);

    // If left subtree is not empty, print left subtree
    if (rootIndex > inStart) {
        printPostOrder(in, pre, inStart, rootIndex - 1, preStart + 1);
    }

    // If right subtree is not empty, print 
  	// right subtree
    if (rootIndex < inEnd) {
        printPostOrder(in, pre, rootIndex + 1, 
                       inEnd, preStart + rootIndex - inStart + 1);
    }

    cout << pre[preStart] << " ";
}

int main() {
  
    vector<int> in = { 4, 2, 5, 1, 3, 6 };
    vector<int> pre = { 1, 2, 4, 5, 3, 6 };
    int n = in.size();
    printPostOrder(in, pre, 0, n - 1, 0);
    return 0;
}
Java
// Java program to print postorder traversal 
// from preorder and inorder traversals

import java.util.Arrays;

class GfG {

    // A utility function to search x in arr[] of size n
    static int search(int[] arr, int x, int n) {
        for (int i = 0; i < n; i++) {
            if (arr[i] == x)
                return i;
        }
        return -1;
    }

    // Prints postorder traversal from given 
    // inorder and preorder traversals
    static void printPostOrder(int[] in, int[] pre, int n) {

        // The first element in pre[] is always root, search it
        // in in[] to find left and right subtrees
        int root = search(in, pre[0], n);

        // If left subtree is not empty, print left subtree
        if (root != 0)
            printPostOrder(Arrays.copyOfRange(in, 0, root), 
                           Arrays.copyOfRange(pre, 1, n), root);

        // If right subtree is not empty, print right subtree
        if (root != n - 1)
            printPostOrder(Arrays.copyOfRange(in, root + 1, n), 
                           Arrays.copyOfRange(pre, root + 1, n), n - root - 1);

        System.out.print(pre[0] + " ");
    }

    public static void main(String[] args) {
      
        int[] in = {4, 2, 5, 1, 3, 6};
        int[] pre = {1, 2, 4, 5, 3, 6};
        int n = in.length;
        printPostOrder(in, pre, n);
    }
}
Python
# Python program to print postorder traversal 
# from preorder and inorder traversals

# A utility function to search x in arr[] of size n
def search(arr, x, n):
    for i in range(n):
        if arr[i] == x:
            return i
    return -1

# Prints postorder traversal from given 
# inorder and preorder traversals
def printPostOrder(inorder, preorder, n):

    # The first element in preorder[] is always root, search it
    # in inorder[] to find left and right subtrees
    root = search(inorder, preorder[0], n)

    # If left subtree is not empty, print
    # left subtree
    if root != 0:
        printPostOrder(inorder[:root], preorder[1:], root)

    # If right subtree is not empty, print 
    # right subtree
    if root != n - 1:
        printPostOrder(inorder[root + 1:], \
                       preorder[root + 1:], n - root - 1)

    print(preorder[0], end=" ")

inorder = [4, 2, 5, 1, 3, 6]
preorder = [1, 2, 4, 5, 3, 6]
n = len(inorder)
printPostOrder(inorder, preorder, n)
C#
// C# program to print postorder traversal
// from preorder and inorder traversals

using System;

class GfG {

    // A utility function to search x
    // in []arr of size n
    static int search(int[] arr, int x, int n) {
        for (int i = 0; i < n; i++)
            if (arr[i] == x)
                return i;
        return -1;
    }

    // Prints postorder traversal from
    // given inorder and preorder traversals
    static void printPostOrder(int[] in1, int[] pre, int n) {

        // The first element in pre[] is
        // always root, search it in in[]
        // to find left and right subtrees
        int root = search(in1, pre[0], n);

        // If left subtree is not empty,
        // print left subtree
        int[] ar;
        if (root != 0) {
            ar = new int[n - 1];
            Array.Copy(pre, 1, ar, 0, n - 1);
            printPostOrder(in1, ar, root);
        }

        // If right subtree is not empty,
        // print right subtree
        if (root != n - 1) {
            ar = new int[n - (root + 1)];
            Array.Copy(in1, root + 1, ar, 0, n - (root + 1));
            int[] ar1 = new int[n - (root + 1)];
            Array.Copy(pre, root + 1, ar1, 0, n - (root + 1));
            printPostOrder(ar, ar1, n - root - 1);
        }

        Console.Write(pre[0] + " ");
    }
  
    static void Main(String[] args) {
      
        int[] in1 = { 4, 2, 5, 1, 3, 6 };
        int[] pre = { 1, 2, 4, 5, 3, 6 };
        int n = in1.Length;
        printPostOrder(in1, pre, n);
    }
}
JavaScript
// JavaScript program to print postorder traversal 
// from preorder and inorder traversals

// A utility function to search x in arr[] of size n
function search(arr, x, n) {
    for (let i = 0; i < n; i++) {
        if (arr[i] === x) {
            return i;
        }
    }
    return -1;
}

// Prints postorder traversal from given 
// inorder and preorder traversals
function printPostOrder(inorder, preorder, n) {

    // The first element in preorder[] is always root, search it
    // in inorder[] to find left and right subtrees
    let root = search(inorder, preorder[0], n);

    // If left subtree is not empty, print
    // left subtree
    if (root !== 0) {
        printPostOrder(inorder.slice(0, root),
        				preorder.slice(1), root);
    }

    // If right subtree is not empty, 
    // print right subtree
    if (root !== n - 1) {
        printPostOrder(inorder.slice(root + 1), 
        preorder.slice(root + 1), n - root - 1);
    }
    
    console.log(preorder[0] + " ");
}

let inorder = [4, 2, 5, 1, 3, 6];
let preorder = [1, 2, 4, 5, 3, 6];
let n = inorder.length;
printPostOrder(inorder, preorder, n);

Output
4 5 2 6 3 1 

[Expected approach] Using Hashing - O(n) Time and O(n) Space

The above solution can be optimized using hashing. We use a HashMap to store elements and their indexes so that we can quickly find the index of an element. 

Below is the implementation of the above approach: 

C++
// C++ program to print Postorder traversal from 
// given Inorder and Preorder traversals.
#include <iostream>
#include <vector>
#include <unordered_map>
using namespace std;

void printPost(vector<int>& in, vector<int>& pre, int inStrt,
               int inEnd, unordered_map<int, int>& mp, int& preIndex) {
    if (inStrt > inEnd)
        return;

    // Find index of next item in preorder 
  	// traversal in inorder.
    int inIndex = mp[pre[preIndex++]];

    // Traverse left tree
    printPost(in, pre, inStrt, inIndex - 1, mp, preIndex);

    // Traverse right tree
    printPost(in, pre, inIndex + 1, inEnd, mp, preIndex);

    cout << in[inIndex] << " ";
}

void printPostOrder(vector<int>& in, vector<int>& pre) {
  
    // Map to store the elements
    unordered_map<int, int> mp;
    int preIndex = 0;

    for (int i = 0; i < in.size(); i++)
      
        // Store index of each element to
      	// access it later
        mp[in[i]] = i;

    printPost(in, pre, 0, in.size() - 1, mp, preIndex);
}

int main() {
    vector<int> in = {4, 2, 5, 1, 3, 6};
    vector<int> pre = {1, 2, 4, 5, 3, 6};

    printPostOrder(in, pre);
    return 0;
}
Java
// Java program to print Postorder traversal from
// given Inorder and Preorder traversals.

import java.util.HashMap;

class GfG {

    // Function to print postorder traversal
    static void printPost(int[] in, int[] pre, int inStart,
                          int inEnd,
                          HashMap<Integer, Integer> mp,
                          int[] preIndex) {
        if (inStart > inEnd)
            return;

        // Find index of next item in preorder traversal in
        // inorder.
        int inIndex = mp.get(pre[preIndex[0]++]);

        // Traverse left tree
        printPost(in, pre, inStart, inIndex - 1, mp,
                  preIndex);

        // Traverse right tree
        printPost(in, pre, inIndex + 1, inEnd, mp,
                  preIndex);

        // Print root node at the end of traversal
        System.out.print(in[inIndex] + " ");
    }

    // Wrapper function to initialize map and call printPost
    static void printPostOrder(int[] in, int[] pre, int n) {
      
        // Map to store the elements
        HashMap<Integer, Integer> mp = new HashMap<>();
        int[] preIndex = { 0 };
      
        // Store index of each element to
      	// access it later
        for (int i = 0; i < n; i++)
            mp.put(in[i], i);

        printPost(in, pre, 0, n - 1, mp, preIndex);
    }

    public static void main(String[] args) {
      
        int[] in = { 4, 2, 5, 1, 3, 6 };
        int[] pre = { 1, 2, 4, 5, 3, 6 };
        int n = pre.length;

        printPostOrder(in, pre, n);
    }
}
Python
# Python program to print Postorder traversal from
# given Inorder and Preorder traversals.

# Function to print postorder traversal
def printPost(inorder, preorder, inStart, inEnd, mp, preIndex):
    if inStart > inEnd:
        return

    # Find index of next item in preorder
    # traversal in inorder
    inIndex = mp[preorder[preIndex[0]]]
    preIndex[0] += 1

    # Traverse left tree
    printPost(inorder, preorder, inStart, \
              inIndex - 1, mp, preIndex)

    # Traverse right tree
    printPost(inorder, preorder, inIndex + 1, \
              inEnd, mp, preIndex)

    # Print root node at the end of traversal
    print(inorder[inIndex], end=" ")

# Wrapper function to initialize map
# and call printPost
def printPostOrder(inorder, preorder):
    mp = {val: idx for idx, val in enumerate(inorder)}

    # Use a list to hold the mutable
    # index
    preIndex = [0]
    printPost(inorder, preorder, 0, len(inorder) - 1,\
              mp, preIndex)


inorder = [4, 2, 5, 1, 3, 6]
preorder = [1, 2, 4, 5, 3, 6]
n = len(preorder)
printPostOrder(inorder, preorder)
C#
// C# program to print Postorder traversal from
// given Inorder and Preorder traversals.

using System;
using System.Collections.Generic;

class GfG {

    // Function to print postorder traversal
    static void PrintPost(int[] inorder, int[] preorder,
                          int inStart, int inEnd,
                          Dictionary<int, int> mp,
                          ref int preIndex) {
        if (inStart > inEnd)
            return;

        // Find index of next item in preorder traversal in
        // inorder.
        int inIndex = mp[preorder[preIndex++]];

        // Traverse left tree
        PrintPost(inorder, preorder, inStart, inIndex - 1,
                  mp, ref preIndex);

        // Traverse right tree
        PrintPost(inorder, preorder, inIndex + 1, inEnd, mp,
                  ref preIndex);

        // Print root node at the end of traversal
        Console.Write(inorder[inIndex] + " ");
    }

    // Wrapper function to initialize 
  	// map and call PrintPost
    static void printPostOrder(int[] inorder, int[] preorder,
                              int n) {

        // Dictionary to store the elements
        Dictionary<int, int> mp
            = new Dictionary<int, int>();
        int preIndex = 0;

        // Store index of each element
        // to access it later
        for (int i = 0; i < n; i++)
            mp[inorder[i]] = i;

        PrintPost(inorder, preorder, 0, n - 1, mp,
                  ref preIndex);
    }

    static void Main(string[] args) {

        int[] inorder = { 4, 2, 5, 1, 3, 6 };
        int[] preorder = { 1, 2, 4, 5, 3, 6 };
        int n = preorder.Length;
        printPostOrder(inorder, preorder, n);
    }
}
JavaScript
// Javascript program to print Postorder traversal from
// given Inorder and Preorder traversals.

function printPost(inorder, pre, inStrt, inEnd, mp,
                   preIndexObj, result) {
    if (inStrt > inEnd)
        return;

    // Get the current index of the preorder element
    const preIndex = preIndexObj.index;
    const inIndex = mp.get(pre[preIndex]);

    // Increment preIndex for 
    // the next call
    preIndexObj.index++;

    // Traverse left tree
    printPost(inorder, pre, inStrt, inIndex - 1, mp,
              preIndexObj, result);

    // Traverse right tree
    printPost(inorder, pre, inIndex + 1, inEnd, mp,
              preIndexObj, result);

    // Add the current node to
    // the result
    result.push(inorder[inIndex]);
}

function printPostOrder(inorder, pre) {

    // Map to store the elements
    const mp = new Map();
    const preIndexObj = {index : 0};
    const result = [];

    for (let i = 0; i < inorder.length; i++) {
    
        // Store index of each element to
        // access it later
        mp.set(inorder[i], i);
    }

    printPost(inorder, pre, 0, inorder.length - 1, mp,
              preIndexObj, result);

    console.log(result.join(" "));
}

const inorder = [ 4, 2, 5, 1, 6, 3 ];
const preorder = [ 1, 2, 4, 5, 3, 6 ];

printPostOrder(inorder, preorder);

Output
4 5 2 6 3 1 

Next Article
Article Tags :
Practice Tags :

Similar Reads