A critical point in a linked list is defined as either a local maxima or a local minima.
A node is a local maxima if the current node has a value strictly greater than the previous node and the next node.
A node is a local minima if the current node has a value strictly smaller than the previous node and the next node.
Note that a node can only be a local maxima/minima if there exists both a previous node and a next node.
Given a linked list head
, return an array of length 2 containing [minDistance, maxDistance]
where minDistance
is the minimum distance between any two distinct critical points and maxDistance
is the maximum distance between any two distinct critical points. If there are fewer than two critical points, return [-1, -1]
.
Example 1:
head = [3,1]
Output: [-1,-1]
Example 2:
head = [5,3,1,2,5,1,2]
Output: [1,3]
Example 3:
head = [1,3,2,2,3,2,2,2,7]
Output: [3,3]
The most straightforward approach is to iterate through the linked list, identify all critical points, and then calculate the minimum and maximum distances between them. This involves:
Code Example (Python):
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
def critical_points(head):
if not head or not head.next:
return [-1, -1]
arr = []
while head:
arr.append(head.val)
head = head.next
critical_indices = []
for i in range(1, len(arr) - 1):
if arr[i-1] < arr[i] > arr[i+1] or arr[i-1] > arr[i] < arr[i+1]:
critical_indices.append(i)
if len(critical_indices) < 2:
return [-1, -1]
min_dist = float('inf')
max_dist = 0
for i in range(len(critical_indices)):
for j in range(i + 1, len(critical_indices)):
dist = abs(critical_indices[i] - critical_indices[j])
min_dist = min(min_dist, dist)
max_dist = max(max_dist, dist)
return [min_dist, max_dist]
Big O Analysis:
A more efficient approach involves traversing the linked list only once, identifying critical points on the fly, and keeping track of the minimum and maximum distances.
first_critical
and last_critical
to -1.Code Example (Python):
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
def critical_points_optimal(head):
if not head or not head.next or not head.next.next:
return [-1, -1]
prev = head
curr = head.next
next_node = head.next.next
index = 1
first_critical = -1
last_critical = -1
min_dist = float('inf')
max_dist = 0
while next_node:
if prev.val < curr.val > next_node.val or prev.val > curr.val < next_node.val:
if first_critical == -1:
first_critical = index
last_critical = index
else:
min_dist = min(min_dist, index - last_critical)
max_dist = index - first_critical
last_critical = index
prev = curr
curr = next_node
next_node = next_node.next if next_node.next else None
index += 1
if min_dist == float('inf'):
return [-1, -1]
else:
return [min_dist, max_dist]
Big O Analysis:
[-1, -1]
.[-1, -1]
.[-1, -1]
.The optimal solution offers significant efficiency by traversing the linked list only once and using constant extra space. The naive solution, while easier to understand, suffers from a higher time complexity due to the need to store linked list values and perform nested iterations for calculating distances.