Point to next higher value node in a linked list with an arbitrary pointer
Last Updated :
11 Feb, 2025
Given a singly linked list with every node having an additional arbitrary pointer that currently points to NULL. The task is to make the arbitrary pointer point to the next higher-value node.

A Simple Solution is to traverse all nodes one by one, for every node, find the node that has the next greater value of the current node and change the next pointer. Time Complexity of this solution is O(n^2).
Using Merge Sort - O(nlogn) Time and O(n) Space
The approach involves using a modified Merge Sort for linked list while maintaining the original sequence and linking each node to the next higher value using an auxiliary arbit pointer. Initially, the arbit pointer of each node is set to point to the next node. The list is recursively split into smaller sections, which are then sorted and merged back together. During merging, the arbit pointers are updated to point to the next higher value node. This method efficiently sorts the list and adjusts the arbit pointers to maintain the desired order without altering the original list structure.
C++
// C++ implementation to point to next higher value
// with an arbitrary pointer using merge sort approach
#include <iostream>
using namespace std;
class Node {
public:
int data;
Node* next;
// Pointer to next higher node
Node* arbit;
Node(int x) {
data = x;
next = nullptr;
arbit = nullptr;
}
};
// Function to merge two sorted lists
Node* SortedMerge(Node* left, Node* right) {
// If one list is empty, return the other
if (!left) return right;
if (!right) return left;
Node* result = nullptr;
Node* curr = nullptr;
// Initialize result with the smaller node
if (left->data <= right->data) {
result = left;
left = left->arbit;
} else {
result = right;
right = right->arbit;
}
curr = result;
// Merge the two lists
while (left && right) {
if (left->data <= right->data) {
curr->arbit = left;
left = left->arbit;
} else {
curr->arbit = right;
right = right->arbit;
}
curr = curr->arbit;
}
// Attach remaining nodes
curr->arbit = left ? left : right;
return result;
}
// Function to split the list into two halves
Node* split(Node* head) {
// If list is empty or has one node
if (!head || !head->arbit) return nullptr;
Node* slow = head;
Node* fast = head->arbit;
// Move slow and fast pointers to find middle
while (fast && fast->arbit) {
slow = slow->arbit;
fast = fast->arbit->arbit;
}
// Split the list into two halves
Node* second = slow->arbit;
slow->arbit = nullptr;
return second;
}
// Recursive merge sort for arbit pointers
Node* MergeSort(Node* head) {
// If list is empty or has one node
if (!head || !head->arbit) return head;
// Split the list into two halves
Node* left = head;
Node* right = split(head);
// Recursively sort both halves
left = MergeSort(left);
right = MergeSort(right);
// Merge the two sorted halves
return SortedMerge(left, right);
}
// Function to populate arbit pointers
Node* populateArbit(Node* head) {
Node* curr = head;
// Initialize arbit pointers to next nodes
while (curr) {
curr->arbit = curr->next;
curr = curr->next;
}
// Sort the list using arbit pointers
return MergeSort(head);
}
void printListArbit(Node* node) {
Node* curr = node;
while (curr) {
cout << curr->data << " ";
curr = curr->arbit;
}
cout << endl;
}
int main() {
// Create a hardcoded linked list
// List: 5 -> 10 -> 2 -> 3
Node* head = new Node(5);
head->next = new Node(10);
head->next->next = new Node(2);
head->next->next->next = new Node(3);
// Populate arbit pointers to next higher node
head = populateArbit(head);
printListArbit(head);
return 0;
}
Java
// Java implementation to point to next higher value
// with an arbitrary pointer using merge sort approach
class Node {
int data;
Node next;
// Pointer to next higher node
Node arbit;
Node(int x) {
data = x;
next = null;
arbit = null;
}
}
class GfG {
// Function to merge two sorted lists
public static Node SortedMerge(Node left, Node right) {
// If one list is empty, return the other
if (left == null) return right;
if (right == null) return left;
Node result = null;
Node curr = null;
// Initialize result with the smaller node
if (left.data <= right.data) {
result = left;
left = left.arbit;
} else {
result = right;
right = right.arbit;
}
curr = result;
// Merge the two lists
while (left != null && right != null) {
if (left.data <= right.data) {
curr.arbit = left;
left = left.arbit;
} else {
curr.arbit = right;
right = right.arbit;
}
curr = curr.arbit;
}
// Attach remaining nodes
curr.arbit = (left != null) ? left : right;
return result;
}
// Function to split the list into two halves
public static Node split(Node head) {
// If list is empty or has one node
if (head == null || head.arbit == null) return null;
Node slow = head;
Node fast = head.arbit;
// Move slow and fast pointers to find middle
while (fast != null && fast.arbit != null) {
slow = slow.arbit;
fast = fast.arbit.arbit;
}
// Split the list into two halves
Node second = slow.arbit;
slow.arbit = null;
return second;
}
// Recursive merge sort for arbit pointers
public static Node MergeSort(Node head) {
// If list is empty or has one node
if (head == null || head.arbit == null) return head;
// Split the list into two halves
Node left = head;
Node right = split(head);
// Recursively sort both halves
left = MergeSort(left);
right = MergeSort(right);
// Merge the two sorted halves
return SortedMerge(left, right);
}
// Function to populate arbit pointers
public static Node populateArbit(Node head) {
Node curr = head;
// Initialize arbit pointers to next nodes
while (curr != null) {
curr.arbit = curr.next;
curr = curr.next;
}
// Sort the list using arbit pointers
return MergeSort(head);
}
public static void printListArbit(Node node) {
Node curr = node;
while (curr != null) {
System.out.print(curr.data + " ");
curr = curr.arbit;
}
System.out.println();
}
public static void main(String[] args) {
// Create a hardcoded linked list
// List: 5 -> 10 -> 2 -> 3
Node head = new Node(5);
head.next = new Node(10);
head.next.next = new Node(2);
head.next.next.next = new Node(3);
// Populate arbit pointers to next higher node
head = populateArbit(head);
printListArbit(head);
}
}
Python
# Python program to point to next higher value
# with an arbitrary pointer using merge sort approach
class Node:
def __init__(self, x):
self.data = x
self.next = None
self.arbit = None
# Function to merge two sorted lists
def SortedMerge(left, right):
# If one list is empty, return the other
if not left:
return right
if not right:
return left
result = None
curr = None
# Initialize result with the smaller node
if left.data <= right.data:
result = left
left = left.arbit
else:
result = right
right = right.arbit
curr = result
# Merge the two lists
while left and right:
if left.data <= right.data:
curr.arbit = left
left = left.arbit
else:
curr.arbit = right
right = right.arbit
curr = curr.arbit
# Attach remaining nodes
curr.arbit = left if left else right
return result
# Function to split the list into two halves
def split(head):
# If list is empty or has one node
if not head or not head.arbit:
return None
slow = head
fast = head.arbit
# Move slow and fast pointers to find middle
while fast and fast.arbit:
slow = slow.arbit
fast = fast.arbit.arbit
# Split the list into two halves
second = slow.arbit
slow.arbit = None
return second
# Recursive merge sort for arbit pointers
def MergeSort(head):
# If list is empty or has one node
if not head or not head.arbit:
return head
# Split the list into two halves
left = head
right = split(head)
# Recursively sort both halves
left = MergeSort(left)
right = MergeSort(right)
# Merge the two sorted halves
return SortedMerge(left, right)
# Function to populate arbit pointers
def populateArbit(head):
curr = head
# Initialize arbit pointers to next nodes
while curr:
curr.arbit = curr.next
curr = curr.next
# Sort the list using arbit pointers
return MergeSort(head)
def printListArbit(node):
curr = node
while curr:
print(curr.data, end=" ")
curr = curr.arbit
print()
if __name__ == "__main__":
# Create a hardcoded linked list
# List: 5 -> 10 -> 2 -> 3
head = Node(5)
head.next = Node(10)
head.next.next = Node(2)
head.next.next.next = Node(3)
# Populate arbit pointers to next higher node
head = populateArbit(head)
printListArbit(head)
C#
// C# program to point to next higher value
// with an arbitrary pointer using merge sort approach
using System;
class Node {
public int data;
public Node next;
// Pointer to next higher node
public Node arbit;
public Node(int x) {
data = x;
next = null;
arbit = null;
}
}
class GfG {
// Function to merge two sorted lists
public static Node SortedMerge(Node left, Node right) {
// If one list is empty, return the other
if (left == null) return right;
if (right == null) return left;
Node result = null;
Node curr = null;
// Initialize result with the smaller node
if (left.data <= right.data) {
result = left;
left = left.arbit;
} else {
result = right;
right = right.arbit;
}
curr = result;
// Merge the two lists
while (left != null && right != null) {
if (left.data <= right.data) {
curr.arbit = left;
left = left.arbit;
} else {
curr.arbit = right;
right = right.arbit;
}
curr = curr.arbit;
}
// Attach remaining nodes
curr.arbit = (left != null) ? left : right;
return result;
}
// Function to split the list into two halves
public static Node Split(Node head) {
// If list is empty or has one node
if (head == null || head.arbit == null) return null;
Node slow = head;
Node fast = head.arbit;
// Move slow and fast pointers to find middle
while (fast != null && fast.arbit != null) {
slow = slow.arbit;
fast = fast.arbit.arbit;
}
// Split the list into two halves
Node second = slow.arbit;
slow.arbit = null;
return second;
}
// Recursive merge sort for arbit pointers
public static Node MergeSort(Node head) {
// If list is empty or has one node
if (head == null || head.arbit == null) return head;
// Split the list into two halves
Node left = head;
Node right = Split(head);
// Recursively sort both halves
left = MergeSort(left);
right = MergeSort(right);
// Merge the two sorted halves
return SortedMerge(left, right);
}
// Function to populate arbit pointers
public static Node PopulateArbit(Node head) {
Node curr = head;
// Initialize arbit pointers to next nodes
while (curr != null) {
curr.arbit = curr.next;
curr = curr.next;
}
// Sort the list using arbit pointers
return MergeSort(head);
}
public static void PrintListArbit(Node node) {
Node curr = node;
while (curr != null) {
Console.Write(curr.data + " ");
curr = curr.arbit;
}
Console.WriteLine();
}
public static void Main() {
// Create a hardcoded linked list
// List: 5 -> 10 -> 2 -> 3
Node head = new Node(5);
head.next = new Node(10);
head.next.next = new Node(2);
head.next.next.next = new Node(3);
// Populate arbit pointers to next higher node
head = PopulateArbit(head);
PrintListArbit(head);
}
}
JavaScript
// JavaScript implementation to point to next higher value
// with an arbitrary pointer using merge sort approach
class Node {
constructor(x) {
this.data = x;
this.next = null;
this.arbit = null;
}
}
// Function to merge two sorted lists
function SortedMerge(left, right) {
// If one list is empty, return the other
if (!left) return right;
if (!right) return left;
let result = null;
let curr = null;
// Initialize result with the smaller node
if (left.data <= right.data) {
result = left;
left = left.arbit;
} else {
result = right;
right = right.arbit;
}
curr = result;
// Merge the two lists
while (left && right) {
if (left.data <= right.data) {
curr.arbit = left;
left = left.arbit;
} else {
curr.arbit = right;
right = right.arbit;
}
curr = curr.arbit;
}
// Attach remaining nodes
curr.arbit = left ? left : right;
return result;
}
// Function to split the list into two halves
function split(head) {
// If list is empty or has one node
if (!head || !head.arbit) return null;
let slow = head;
let fast = head.arbit;
// Move slow and fast pointers to find middle
while (fast && fast.arbit) {
slow = slow.arbit;
fast = fast.arbit.arbit;
}
// Split the list into two halves
let second = slow.arbit;
slow.arbit = null;
return second;
}
// Recursive merge sort for arbit pointers
function MergeSort(head) {
// If list is empty or has one node
if (!head || !head.arbit) return head;
// Split the list into two halves
let left = head;
let right = split(head);
// Recursively sort both halves
left = MergeSort(left);
right = MergeSort(right);
// Merge the two sorted halves
return SortedMerge(left, right);
}
// Function to populate arbit pointers
function populateArbit(head) {
let curr = head;
// Initialize arbit pointers to next nodes
while (curr) {
curr.arbit = curr.next;
curr = curr.next;
}
// Sort the list using arbit pointers
return MergeSort(head);
}
function printListArbit(node) {
let curr = node;
while (curr) {
process.stdout.write(curr.data + " ");
curr = curr.arbit;
}
console.log();
}
// Create a hardcoded linked list
// 5 -> 10 -> 2 -> 3
let head = new Node(5);
head.next = new Node(10);
head.next.next = new Node(2);
head.next.next.next = new Node(3);
// Populate arbit pointers to next higher node
head = populateArbit(head);
printListArbit(head);
Time Complexity: O(nlogn), as we are using the Merge Sort technique
Auxiliary Space: O(n) , where n is number of elements in linked list.