Count Pairs Violating BST Property

Last Updated : 10 Sep, 2026

Given a binary tree, count pairs of nodes that violate any of the following Binary Search Tree (BST) properties.

  • All values in the left subtree are strictly smaller.
  • All values in the right subtree are strictly greater.

Examples: 

Input: root[] = [10, 50, 40, N, N, 20, 30]
2056958715
Output: 5
Explanation: Pairs violating BST property are:
(10,50), 10 should be greater than its left child value.
(40,30), 40 should be less than its right child value.
(50,20), (50,30) and (50,40), maximum of left subtree of 10 is 50 greater than 20, 30 and 40 of its right subtree.

Input: root[] = [80, 40, 30, 70, N, 60, 70]
2056958716Output: 9
Explanation: There are total 9 pairs (80,30),(80,60),(80,70),(30,60),(40,70),(40,30),(70,30),(70,60),(70,70) which violate the BST properties.

Try It Yourself
redirect icon

[Naive Approach] Check All Pairs in Inorder Traversal - O(n^2) Time and O(n) Space

The idea is to first perform an inorder traversal and store the node values in an array.

In a valid BST, this array should be sorted in strictly increasing order. Therefore, every pair (i, j) where i < j and arr[i] > arr[j] represents a pair that violates the BST property.

Working of the Approach:

  • Perform inorder traversal of the binary tree and store all node values.
  • Initialize the count of violating pairs as 0.
  • Consider every pair of indices (i, j) where i < j.
  • If arr[i] > arr[j], increment the count.
  • Return the total count.
C++
#include <bits/stdc++.h>
using namespace std;

struct Node {
    int data;
    Node* left;
    Node* right;

    Node(int val) {
        data = val;
        left = right = nullptr;
    }
};

void inorder(Node* root, vector<int>& arr) {
    if (root == nullptr)
        return;

    inorder(root->left, arr);
    arr.push_back(root->data);
    inorder(root->right, arr);
}

int pairsViolatingBST(Node* root) {
    vector<int> arr;
    inorder(root, arr);

    int count = 0;

    // Count inversion pairs in inorder traversal.
    for (int i = 0; i < arr.size(); i++) {
        for (int j = i + 1; j < arr.size(); j++) {
            if (arr[i] > arr[j])
                count++;
        }
    }

    return count;
}

int main() {
    Node* root = new Node(10);
    root->left = new Node(50);
    root->right = new Node(40);

    root->right->left = new Node(20);
    root->right->right = new Node(30);

    cout << pairsViolatingBST(root) << endl;

    return 0;
}
Java
import java.util.ArrayList;

class Node {
    int data;
    Node left, right;

    Node(int val) {
        data = val;
        left = right = null;
    }
}

class GFG {
    static void inorder(Node root, ArrayList<Integer> arr) {
        if (root == null)
            return;

        inorder(root.left, arr);
        arr.add(root.data);
        inorder(root.right, arr);
    }

    static int pairsViolatingBST(Node root) {
        ArrayList<Integer> arr = new ArrayList<>();
        inorder(root, arr);

        int count = 0;

        // Count inversion pairs in inorder traversal.
        for (int i = 0; i < arr.size(); i++) {
            for (int j = i + 1; j < arr.size(); j++) {
                if (arr.get(i) > arr.get(j))
                    count++;
            }
        }

        return count;
    }

    public static void main(String[] args) {
        Node root = new Node(10);
        root.left = new Node(50);
        root.right = new Node(40);

        root.right.left = new Node(20);
        root.right.right = new Node(30);

        System.out.println(pairsViolatingBST(root));
    }
}
Python
class Node:
    def __init__(self, val):
        self.data = val
        self.left = None
        self.right = None


def inorder(root, arr):
    if root is None:
        return

    inorder(root.left, arr)
    arr.append(root.data)
    inorder(root.right, arr)


def pairsViolatingBST(root):
    arr = []
    inorder(root, arr)

    count = 0

    # Count inversion pairs in inorder traversal.
    for i in range(len(arr)):
        for j in range(i + 1, len(arr)):
            if arr[i] > arr[j]:
                count += 1

    return count


if __name__ == "__main__":
    root = Node(10)
    root.left = Node(50)
    root.right = Node(40)

    root.right.left = Node(20)
    root.right.right = Node(30)

    print(pairsViolatingBST(root))
C#
using System;
using System.Collections.Generic;

class Node
{
    public int data;
    public Node left;
    public Node right;

    public Node(int val)
    {
        data = val;
        left = right = null;
    }
}

class GFG
{
    static void inorder(Node root, List<int> arr)
    {
        if (root == null)
            return;

        inorder(root.left, arr);
        arr.Add(root.data);
        inorder(root.right, arr);
    }

    static int pairsViolatingBST(Node root)
    {
        List<int> arr = new List<int>();
        inorder(root, arr);

        int count = 0;

        // Count inversion pairs in inorder traversal.
        for (int i = 0; i < arr.Count; i++)
        {
            for (int j = i + 1; j < arr.Count; j++)
            {
                if (arr[i] > arr[j])
                    count++;
            }
        }

        return count;
    }

    static void Main()
    {
        Node root = new Node(10);
        root.left = new Node(50);
        root.right = new Node(40);

        root.right.left = new Node(20);
        root.right.right = new Node(30);

        Console.WriteLine(pairsViolatingBST(root));
    }
}
JavaScript
class Node {
    constructor(data) {
        this.data = data;
        this.left = null;
        this.right = null;
    }
}

function inorder(root, arr) {
    if (root === null)
        return;

    inorder(root.left, arr);
    arr.push(root.data);
    inorder(root.right, arr);
}

function pairsViolatingBST(root) {
    let arr = [];
    inorder(root, arr);

    let count = 0;

    // Count inversion pairs in inorder traversal.
    for (let i = 0; i < arr.length; i++) {
        for (let j = i + 1; j < arr.length; j++) {
            if (arr[i] > arr[j])
                count++;
        }
    }

    return count;
}

// Driver Code
const root = new Node(10);
root.left = new Node(50);
root.right = new Node(40);

root.right.left = new Node(20);
root.right.right = new Node(30);

console.log(pairsViolatingBST(root));

Output
5

[Expected Approach] Count Inversions Using Merge Sort - O(n log n) Time and O(n) Space

The idea is to observe that the inorder traversal of a valid BST must be strictly increasing.

Therefore, every pair of values in the inorder traversal where an earlier value is greater than a later value represents a pair violating the BST property.

Instead of checking all pairs in O(n2), we count these inversions efficiently using Merge Sort in O(n log n) time.

Working of the Approach:

  • Perform an inorder traversal of the binary tree and store all node values in an array.
  • Apply Merge Sort on this array while counting inversions.
  • During the merge step, if an element from the right half is smaller than an element from the left half, all remaining elements in the left half also form violating pairs with it.
  • Add the number of such remaining elements to the count.
  • Continue merging until the entire array is processed.
  • Return the total inversion count as the number of pairs violating the BST property.
C++
#include <bits/stdc++.h>
using namespace std;

struct Node {
    int data;
    Node* left;
    Node* right;

    Node(int val) {
        data = val;
        left = right = nullptr;
    }
};

void inorder(Node* root, vector<int>& arr) {
    if (root == nullptr)
        return;

    inorder(root->left, arr);
    arr.push_back(root->data);
    inorder(root->right, arr);
}

long long mergeSort(vector<int>& arr, int low, int high) {
    if (low >= high)
        return 0;

    int mid = low + (high - low) / 2;

    long long count = mergeSort(arr, low, mid);
    count += mergeSort(arr, mid + 1, high);

    vector<int> temp;
    int i = low, j = mid + 1;

    while (i <= mid && j <= high) {
        if (arr[i] <= arr[j]) {
            temp.push_back(arr[i++]);
        } else {
            // Count inversions with remaining left elements.
            count += mid - i + 1;
            temp.push_back(arr[j++]);
        }
    }

    while (i <= mid)
        temp.push_back(arr[i++]);

    while (j <= high)
        temp.push_back(arr[j++]);

    for (int k = 0; k < temp.size(); k++)
        arr[low + k] = temp[k];

    return count;
}

int pairsViolatingBST(Node* root) {
    vector<int> arr;
    inorder(root, arr);

    return (int)mergeSort(arr, 0, arr.size() - 1);
}

int main() {
    Node* root = new Node(10);
    root->left = new Node(50);
    root->right = new Node(40);

    root->right->left = new Node(20);
    root->right->right = new Node(30);

    cout << pairsViolatingBST(root) << endl;

    return 0;
}
Java
import java.util.*;

class Node {
    int data;
    Node left, right;

    Node(int val) {
        data = val;
        left = right = null;
    }
}

class GFG {
    static void inorder(Node root, ArrayList<Integer> arr) {
        if (root == null)
            return;

        inorder(root.left, arr);
        arr.add(root.data);
        inorder(root.right, arr);
    }

    static void merge(int[] arr, int low, int mid, int high, long[] count) {
        int[] temp = new int[high - low + 1];
        int i = low, j = mid + 1, k = 0;

        while (i <= mid && j <= high) {
            if (arr[i] <= arr[j]) {
                temp[k++] = arr[i++];
            } else {
                // Count inversions formed with the remaining left elements.
                count[0] += mid - i + 1;
                temp[k++] = arr[j++];
            }
        }

        while (i <= mid)
            temp[k++] = arr[i++];

        while (j <= high)
            temp[k++] = arr[j++];

        for (i = low, k = 0; i <= high; i++, k++)
            arr[i] = temp[k];
    }

    static void mergeSort(int[] arr, int low, int high, long[] count) {
        if (low >= high)
            return;

        int mid = low + (high - low) / 2;

        mergeSort(arr, low, mid, count);
        mergeSort(arr, mid + 1, high, count);
        merge(arr, low, mid, high, count);
    }

    static int pairsViolatingBST(Node root) {
        ArrayList<Integer> list = new ArrayList<>();
        inorder(root, list);

        int[] arr = new int[list.size()];
        for (int i = 0; i < list.size(); i++)
            arr[i] = list.get(i);

        long[] count = {0};
        mergeSort(arr, 0, arr.length - 1, count);

        return (int) count[0];
    }

    public static void main(String[] args) {
        Node root = new Node(10);
        root.left = new Node(50);
        root.right = new Node(40);

        root.right.left = new Node(20);
        root.right.right = new Node(30);

        System.out.println(pairsViolatingBST(root));
    }
}
Python
class Node:
    def __init__(self, val):
        self.data = val
        self.left = None
        self.right = None


def inorder(root, arr):
    if root is None:
        return

    inorder(root.left, arr)
    arr.append(root.data)
    inorder(root.right, arr)


def mergeSort(arr):
    if len(arr) <= 1:
        return arr, 0

    mid = len(arr) // 2

    left, countLeft = mergeSort(arr[:mid])
    right, countRight = mergeSort(arr[mid:])

    merged = []
    i = j = 0
    count = countLeft + countRight

    while i < len(left) and j < len(right):
        if left[i] <= right[j]:
            merged.append(left[i])
            i += 1
        else:
            # Count inversions formed with the remaining left elements.
            count += len(left) - i
            merged.append(right[j])
            j += 1

    merged.extend(left[i:])
    merged.extend(right[j:])

    return merged, count


def pairsViolatingBST(root):
    arr = []
    inorder(root, arr)

    _, count = mergeSort(arr)
    return count


if __name__ == "__main__":
    root = Node(10)
    root.left = Node(50)
    root.right = Node(40)

    root.right.left = Node(20)
    root.right.right = Node(30)

    print(pairsViolatingBST(root))
C#
using System;
using System.Collections.Generic;

class Node
{
    public int data;
    public Node left;
    public Node right;

    public Node(int val)
    {
        data = val;
        left = right = null;
    }
}

class GFG
{
    static void inorder(Node root, List<int> arr)
    {
        if (root == null)
            return;

        inorder(root.left, arr);
        arr.Add(root.data);
        inorder(root.right, arr);
    }

    static void merge(int[] arr, int low, int mid, int high, ref long count)
    {
        int[] temp = new int[high - low + 1];
        int i = low, j = mid + 1, k = 0;

        while (i <= mid && j <= high)
        {
            if (arr[i] <= arr[j])
            {
                temp[k++] = arr[i++];
            }
            else
            {
                // Count inversions formed with the remaining left elements.
                count += mid - i + 1;
                temp[k++] = arr[j++];
            }
        }

        while (i <= mid)
            temp[k++] = arr[i++];

        while (j <= high)
            temp[k++] = arr[j++];

        for (i = low, k = 0; i <= high; i++, k++)
            arr[i] = temp[k];
    }

    static void mergeSort(int[] arr, int low, int high, ref long count)
    {
        if (low >= high)
            return;

        int mid = low + (high - low) / 2;

        mergeSort(arr, low, mid, ref count);
        mergeSort(arr, mid + 1, high, ref count);
        merge(arr, low, mid, high, ref count);
    }

    static int pairsViolatingBST(Node root)
    {
        List<int> list = new List<int>();
        inorder(root, list);

        int[] arr = list.ToArray();
        long count = 0;

        mergeSort(arr, 0, arr.Length - 1, ref count);

        return (int)count;
    }

    static void Main()
    {
        Node root = new Node(10);
        root.left = new Node(50);
        root.right = new Node(40);

        root.right.left = new Node(20);
        root.right.right = new Node(30);

        Console.WriteLine(pairsViolatingBST(root));
    }
}
JavaScript
class Node {
    constructor(data) {
        this.data = data;
        this.left = null;
        this.right = null;
    }
}

function inorder(root, arr) {
    if (root === null)
        return;

    inorder(root.left, arr);
    arr.push(root.data);
    inorder(root.right, arr);
}

function mergeSort(arr) {
    if (arr.length <= 1)
        return [arr, 0];

    let mid = Math.floor(arr.length / 2);

    let [left, countLeft] = mergeSort(arr.slice(0, mid));
    let [right, countRight] = mergeSort(arr.slice(mid));

    let merged = [];
    let i = 0, j = 0;
    let count = countLeft + countRight;

    while (i < left.length && j < right.length) {
        if (left[i] <= right[j]) {
            merged.push(left[i++]);
        } else {
            // Count inversions formed with the remaining left elements.
            count += left.length - i;
            merged.push(right[j++]);
        }
    }

    while (i < left.length)
        merged.push(left[i++]);

    while (j < right.length)
        merged.push(right[j++]);

    return [merged, count];
}

function pairsViolatingBST(root) {
    let arr = [];
    inorder(root, arr);

    let [sorted, count] = mergeSort(arr);

    return count;
}

// Driver Code
const root = new Node(10);
root.left = new Node(50);
root.right = new Node(40);

root.right.left = new Node(20);
root.right.right = new Node(30);

console.log(pairsViolatingBST(root));

Output
5
Comment