Back to blog
Jan 14, 2026
5 min read

Count Hills and Valleys in an Array

Count indices in an array that are strictly greater or smaller than their neighbors, skipping consecutive duplicates.

Difficulty: Easy | Acceptance: 68.90% | Paid: No Topics: Array

You are given a 0-indexed integer array nums. An index i is part of a hill in nums if the closest non-equal neighbors of i are smaller than nums[i]. Similarly, an index i is part of a valley in nums if the closest non-equal neighbors of i are larger than nums[i]. Adjacent indices i and j are part of the same hill or valley if nums[i] == nums[j]. Note that for an index to be part of a hill or valley, it must have a non-equal neighbor on both the left and right. Return the number of hills and valleys in nums.

Examples

Example 1

Input:

nums = [2,4,1,1,6,5]

Output:

3

Explanation: At index 0: There is no non-equal neighbor of 2 on the left, so index 0 is neither a hill nor a valley. At index 1: The closest non-equal neighbors of 4 are 2 and 1. Since 4 > 2 and 4 > 1, index 1 is a hill. At index 2: The closest non-equal neighbors of 1 are 4 and 6. Since 1 < 4 and 1 < 6, index 2 is a valley. At index 3: The closest non-equal neighbors of 1 are 4 and 6. Since 1 < 4 and 1 < 6, index 3 is a valley, but note that it is part of the same valley as index 2. At index 4: The closest non-equal neighbors of 6 are 1 and 5. Since 6 > 1 and 6 > 5, index 4 is a hill. At index 5: There is no non-equal neighbor of 5 on the right, so index 5 is neither a hill nor a valley. There are 3 hills and valleys so we return 3.

Example 2

Input:

nums = [6,6,5,5,4,1]

Output:

0

Explanation: At index 0: There is no non-equal neighbor of 6 on the left, so index 0 is neither a hill nor a valley. At index 1: There is no non-equal neighbor of 6 on the left, so index 1 is neither a hill nor a valley. At index 2: The closest non-equal neighbors of 5 are 6 and 4. Since 5 < 6 and 5 > 4, index 2 is neither a hill nor a valley. At index 3: The closest non-equal neighbors of 5 are 6 and 4. Since 5 < 6 and 5 > 4, index 3 is neither a hill nor a valley. At index 4: The closest non-equal neighbors of 4 are 5 and 1. Since 4 < 5 and 4 > 1, index 4 is neither a hill nor a valley. At index 5: There is no non-equal neighbor of 1 on the right, so index 5 is neither a hill nor a valley. There are 0 hills and valleys so we return 0.

Constraints

3 <= nums.length <= 100
1 <= nums[i] <= 100

Approach 1: Preprocessing

Intuition The problem requires comparing an element with its closest non-equal neighbors. By removing consecutive duplicates from the array first, we simplify the logic: every element in the new array is distinct from its immediate neighbors, so we can directly check for hills and valleys.

Steps

  • Create a new list unique to store the array with consecutive duplicates removed.
  • Iterate through the original nums array. If the current number is different from the last number added to unique, append it.
  • Iterate through the unique array from index 1 to len(unique) - 2.
  • For each element, check if it is greater than both neighbors (hill) or smaller than both neighbors (valley).
  • Increment the count if the condition is met.
python
class Solution:
    def countHillValley(self, nums: list[int]) -&gt; int:
        unique = []
        for n in nums:
            if not unique or n != unique[-1]:
                unique.append(n)
        
        count = 0
        for i in range(1, len(unique) - 1):
            prev = unique[i - 1]
            curr = unique[i]
            next_val = unique[i + 1]
            if (curr &gt; prev and curr &gt; next_val) or (curr &lt; prev and curr &lt; next_val):
                count += 1
        return count

Complexity

  • Time: O(N) where N is the length of the array. We iterate through the array twice.
  • Space: O(N) to store the unique array.
  • Notes: This approach trades space for simplicity in logic.

Approach 2: Direct Simulation

Intuition Instead of creating a new array, we can iterate through the original array and for each index, explicitly search for the closest non-equal neighbors to the left and right. This avoids extra space usage.

Steps

  • Initialize count to 0.
  • Iterate through each index i in nums.
  • Initialize left to i - 1 and decrement while left is valid and nums[left] == nums[i].
  • Initialize right to i + 1 and increment while right is valid and nums[right] == nums[i].
  • If both left and right are valid indices (meaning we found non-equal neighbors on both sides):
    • Check if nums[i] is strictly greater than both neighbors (hill) or strictly smaller than both (valley).
    • Increment count if true.
  • Return count.
python
class Solution:
    def countHillValley(self, nums: list[int]) -&gt; int:
        n = len(nums)
        count = 0
        for i in range(n):
            left = i - 1
            while left &gt;= 0 and nums[left] == nums[i]:
                left -= 1
            
            right = i + 1
            while right &lt; n and nums[right] == nums[i]:
                right += 1
            
            if left &gt;= 0 and right &lt; n:
                if (nums[i] &gt; nums[left] and nums[i] &gt; nums[right]) or \
                   (nums[i] &lt; nums[left] and nums[i] &lt; nums[right]):
                    count += 1
        return count

Complexity

  • Time: O(N²) in the worst case (e.g., all elements are equal), though typically much faster. Given the constraint N <= 100, this is perfectly acceptable.
  • Space: O(1) as we only use a few variables for pointers and counting.
  • Notes: This approach is space-optimized but can be slower on arrays with many consecutive duplicates.