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.

Easy Python 3.9+ Aug 9, 2026 Lists & loops 14 views 0 copies

Python code

43 lines
Python 3.9+
def 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

stdout
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

  1. 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])]`
  2. 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

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from Lists & loops

Related tutorials and quizzes for this topic.