Find the Minimum and Maximum Number of Nodes Between Critical Points

Updated on 28 May, 2025
Find the Minimum and Maximum Number of Nodes Between Critical Points header image

Problem Statement

In a linked list, a critical point is defined as a node which is either a local maxima or a local minima. Understanding these terms:

  • A node is a local maxima if its value is strictly greater than those of its neighbouring nodes (both previous and next).
  • A node is a local minima if its value is strictly less than those of its neighbouring nodes (both previous and next).

For a node to qualify as a local maximum or minimum, it must have both a predecessor and a successor in the linked list.

The task is to return an array of two integers, [minDistance, maxDistance], based on the critical points found in the given linked list head:

  • minDistance is the smallest distance between any two critical points.
  • maxDistance is the largest distance between any two critical points.

If fewer than two critical points exist in the linked list, the function should return [-1, -1].

Examples

Example 1

Input:

head = [3,1]

Output:

[-1,-1]

Explanation:

There are no critical points in [3,1].

Example 2

Input:

head = [5,3,1,2,5,1,2]

Output:

[1,3]

Explanation:

There are three critical points:
- The third node is a local minima because 1 is less than 3 and 2.
- The fifth node is a local maxima because 5 is greater than 2 and 1.
- The sixth node is a local minima because 1 is less than 5 and 2.

The minimum distance is between the fifth and the sixth node: 6 - 5 = 1.
The maximum distance is between the third and the sixth node: 6 - 3 = 3.

Example 3

Input:

head = [1,3,2,2,3,2,2,2,7]

Output:

[3,3]

Explanation:

There are two critical points:
- The second node is a local maxima because 3 is greater than 1 and 2.
- The fifth node is a local maxima because 3 is greater than 2 and 2.

Both the minimum and maximum distances are between the second and the fifth node: 5 - 2 = 3.

Constraints

  • The number of nodes in the list is in the range [2, 10^5]
  • 1 <= Node.val <= 10^5

Approach and Intuition

To solve this problem, follow these stages:

  1. Traverse the Linked List:

    • Keep track of each node’s index.
    • For each node (excluding the first and last), check if it is a local maxima or minima by comparing it with its previous and next node values.
  2. Store Indices of Critical Points:

    • Add the index of each detected critical point into a list.
  3. Check Critical Point Count:

    • If fewer than two critical points are found, return [-1, -1].
  4. Compute Distances:

    • maxDistance = difference between the first and last critical point indices.
    • minDistance = smallest difference between any two consecutive critical point indices.

This method ensures an O(n) traversal and calculation, which is optimal for the problem's constraints.

Solutions

  • C++
  • Java
  • Python
cpp
class Solution {
public:
    vector<int> criticalPointsDistance(ListNode* head) {
        vector<int> distances = {-1, -1};

        // Maximum value for minimizing
        int minimumInterval = INT_MAX;

        // Setup for current, previous node tracking
        ListNode* prev = head;
        ListNode* curr = head->next;
        int idxCurr = 1;
        int idxPrevCritical = 0;
        int idxFirstCritical = 0;

        // Iterate through list
        while (curr->next != nullptr) {
            // Determine if there's a critical point
            if ((curr->val > prev->val && curr->val > curr->next->val) || 
                (curr->val < prev->val && curr->val < curr->next->val)) {
                // Handle the first found critical point
                if (idxPrevCritical == 0) {
                    idxPrevCritical = idxCurr;
                    idxFirstCritical = idxCurr;
                } else {
                    // Update minimum interval and previous index
                    minimumInterval = min(minimumInterval, idxCurr - idxPrevCritical);
                    idxPrevCritical = idxCurr;
                }
            }

            // Advance pointers
            ++idxCurr;
            prev = curr;
            curr = curr->next;
        }

        // Resolve the results if more than one critical point exists
        if (minimumInterval != INT_MAX) {
            int maxInterval = idxPrevCritical - idxFirstCritical;
            distances = {minimumInterval, maxInterval};
        }

        return distances;
    }
};

This C++ solution finds the minimum and maximum number of nodes between critical points in a linked list. Critical points are nodes where the value is either greater than or less than both its adjacent values. Here's how the solution is implemented:

  • Initialize a vector called distances with values -1, -1 to hold the minimum and maximum intervals between critical points. If there are less than two critical points, the vector remains as -1, -1.

  • Utilize two pointers, prev and curr, to traverse the linked list from the first node. Also maintain idxCurr to keep track of the current node index.

  • For each node in the list (except the first and last), check if it is a critical point. A node is considered as a critical point if:

    • It is greater than both its previous and next nodes.
    • It is less than both its previous and next nodes.
  • If the current node is a critical point and is the first critical point found, store its index in both idxPrevCritical and idxFirstCritical.

  • If another critical point is identified, update the minimumInterval by calculating the difference between the current index and the last previous critical index. Update idxPrevCritical with the current index.

  • Continue this until the end of the list is reached.

  • After the traversal, if at least two critical points were found (i.e., minimumInterval is not INT_MAX), calculate the maxInterval as the difference between the last and first critical indices and update the distances with both the minimum and maximum intervals.

  • Finally, return the distances vector containing the minimum and maximum intervals between critical points if they exist. If there are less than two critical points, it will return -1, -1 indicating no intervals can be determined.

This solution efficiently identifies critical points and measures the intervals by iterating through the linked list once, ensuring a time complexity of O(n), where n is the number of nodes in the list.

java
class Solution {

    public int[] criticalDistance(ListNode head) {
        int[] distance = { -1, -1 };

        // Minimum distance initialized to a large number
        int minDist = Integer.MAX_VALUE;

        // Position markers and previous critical point data
        ListNode prevNode = head;
        ListNode currNode = head.next;
        int currIndex = 1;
        int lastCritIndex = 0;
        int firstCritIndex = 0;

        while (currNode.next != null) {
            // Determine if current node is a critical point
            if (
                (currNode.val < prevNode.val && currNode.val < currNode.next.val) ||
                (currNode.val > prevNode.val && currNode.val > currNode.next.val)
            ) {
                // Handle first critical point found
                if (lastCritIndex == 0) {
                    lastCritIndex = currIndex;
                    firstCritIndex = currIndex;
                } else {
                    // Update minimum distance
                    minDist = Math.min(
                        minDist,
                        currIndex - lastCritIndex
                    );
                    lastCritIndex = currIndex;
                }
            }

            // Progress the pointers
            currIndex++;
            prevNode = currNode;
            currNode = currNode.next;
        }

        // Check if enough critical points were found
        if (minDist != Integer.MAX_VALUE) {
            int maxDist = lastCritIndex - firstCritIndex;
            distance = new int[] { minDist, maxDist };
        }

        return distance;
    }
}

To find the minimum and maximum number of nodes between critical points in a linked list, follow these steps in Java:

  1. Initialize a distance array to {-1, -1} to store the results. If no critical point pairs are found, this will be the result returned.
  2. Set minDist to Integer.MAX_VALUE to track the smallest distance encountered.
  3. Use nodes prevNode and currNode to iterate through the list starting from the head. Use currIndex to track the current node's index.
  4. Initialize lastCritIndex and firstCritIndex to 0 to record indices of critical points.
  5. Process each node until the end of the list (currNode.next != null):
    • Check if a node is a critical point by comparing its value with its neighbors. This includes:
      • A node having a value less than both of its neighbors.
      • A node having a value greater than both of its neighbors.
    • If lastCritIndex is 0 (no critical points found yet), set lastCritIndex and firstCritIndex to the current index.
    • If it's not the first critical point, calculate the distance from the last critical point and update minDist if the current distance is smaller.
    • Move lastCritIndex to the current index.
    • Increment currIndex and progress prevNode and currNode.
  6. After exiting the loop, check if minDist was updated:
    • Calculate the maximum distance (maxDist) as the difference between the last and first critical indices.
    • Set distance array to { minDist, maxDist }.
  7. Return the distance array containing the minimum and maximum distances between critical points. If no critical point pairs are found, the method returns {-1, -1}.

Ensure your linked list contains enough nodes to correctly detect critical points and calculate distances. The above approach provides an efficient method to tackle the problem within a single traversal of the linked list.

python
class Solution:
    def criticalPointsDistance(self, head: Optional[ListNode]) -> List[int]:
        output = [-1, -1]
        minimum_gap = float("inf")
        
        # Setup to navigate the linked list
        prev = head
        current = head.next
        index = 1
        first_crit = 0
        last_crit = 0

        while current.next is not None:
            if (
                current.val < prev.val and current.val < current.next.val
            ) or (
                current.val > prev.val and current.val > current.next.val
            ):
                # Determine distances when a critical point is found
                if last_crit == 0:
                    last_crit = index
                    first_crit = index
                else:
                    minimum_gap = min(minimum_gap, index - last_crit)
                    last_crit = index

            # Move pointers and index forward
            index += 1
            prev = current
            current = current.next

        if minimum_gap != float("inf"):
            maximum_gap = last_crit - first_crit
            output = [minimum_gap, maximum_gap]

        return output

The provided Python code defines a method criticalPointsDistance in the Solution class for finding the minimum and maximum number of nodes between critical points in a linked list. Here is a summary of how this solution works:

  1. Initialize the output list with [-1, -1] to handle cases where there are no valid critical points. minimum_gap is set to infinity to find the minimum distance effectively when encountered.

  2. Use pointers, prev and current, to traverse the linked list. Start from the second node because critical points are related to its adjacent nodes.

  3. Initialize index to track the current node's position and first_crit and last_crit to store the positions of the first and last critical points found.

  4. Loop through the nodes until the second last node (current.next is not None).

  5. Check if the current node is a critical point by comparing its value with the adjacent nodes. A node is considered critical if

    • It is a peak (greater than both its neighbors).
    • It is a valley (smaller than both its neighbors).
  6. If a critical point is found and last_crit is zero (indicating the first critical point):

    • Set last_crit and first_crit to the current index.
    • Else, update minimum_gap with the difference between the index of the current critical point and the index of the last critical point, and update last_crit to the current index.
  7. After the loop, if minimum_gap is less than infinity (indicating that more than one critical point was found):

    • Calculate maximum_gap as the distance between the first and last critical points.
    • Update the output with [minimum_gap, maximum_gap].
  8. Return the output, which contains the minimum and maximum gaps between critical points if at least two critical points are found, or [-1, -1] if fewer than two critical points exist.

This solution essentially scans through the linked list to detect critical points and captures their distances to determine the required minimum and maximum gaps.

Comments

No comments yet.