Find Local Minima (Valleys) in a Numeric List in Python
This code finds indices of all local minima (valleys) in a numeric list, including edge cases, using a simple loop that compares each element with its neighbors.
Python code
43 linesdef find_local_minima(numbers):
"""Find indices of local minima (valleys) in a numeric list.
A value is a local minimum if it's less than or equal to its neighbors.
Edge elements are considered minima if they're less than or equal to their single neighbor.
"""
if not numbers:
return []
if len(numbers) == 1:
return [0]
minima_indices = []
# Check first element
if numbers[0] <= numbers[1]:
minima_indices.append(0)
# Check middle elements
for i in range(1, len(numbers) - 1):
if numbers[i] <= numbers[i - 1] and numbers[i] <= numbers[i + 1]:
minima_indices.append(i)
# Check last element
if numbers[-1] <= numbers[-2]:
minima_indices.append(len(numbers) - 1)
return minima_indices
if __name__ == "__main__":
test_cases = [
[5, 2, 3, 1, 4, 2, 6],
[1, 2, 3, 4, 5],
[5, 4, 3, 2, 1],
[3, 3, 3],
[7]
]
for i, case in enumerate(test_cases):
indices = find_local_minima(case)
values = [case[idx] for idx in indices]
print(f"List {i + 1}: {case}")
print(f"Local minima at indices {indices} with values {values}\n")
Output
List 1: [5, 2, 3, 1, 4, 2, 6]
Local minima at indices [1, 3, 5] with values [2, 1, 2]
List 2: [1, 2, 3, 4, 5]
Local minima at indices [0] with values [1]
List 3: [5, 4, 3, 2, 1]
Local minima at indices [4] with values [1]
List 4: [3, 3, 3]
Local minima at indices [0, 1, 2] with values [3, 3, 3]
List 5: [7]
Local minima at indices [0] with values [7]
How it works
The function checks each element against its immediate neighbors using <= to include plateaus. For edges, it compares with the single neighbor. A single-element list is always a local minimum. The loop iterates from index 1 to len(numbers)-2 to avoid index errors. This approach has O(n) time complexity because each element is checked exactly once.
Common mistakes
- Forgetting to handle empty or single-element lists, causing index errors
- Using `>` instead of `>=` to exclude equal neighbors, which would miss plateaus
- Not treating edge elements as valid minima
- Modifying the list while iterating over it
Variations
- Use a list comprehension: `[i for i in range(len(arr)) if (i==0 or arr[i]<=arr[i-1]) and (i==len(arr)-1 or arr[i]<=arr[i+1])]`
- Employ `numpy` with boolean masking for large arrays (requires numpy)
Real-world use cases
- Detecting troughs in financial time series data to identify buying opportunities
- Finding local minima in sensor readings to trigger alerts when conditions reach a low point
- Analyzing signal data in signal processing to locate valleys for feature extraction
Sponsored
More from Lists & loops
- Check if List is Sorted Ascending in Python easy
- Compare Two Lists in Python: Common, Only in First, Only in Second easy
- Convert a List of Integers to a Comma-Separated String in Python easy
- Enumerate a Python List with a Custom Start Index easy
- Extract Data by Type from a List in Python: Numbers and Strings easy
- Find All Occurrences of an Item in a Python List easy
Keep learning
Related tutorials and quizzes for this topic.