Hi👋SpeedAlgo • Deliberate Practice & Cognitive Ergonomics for Software Engineers

An interactive algorithm mastery and technical interview preparation platform published by Hi👋WebEnterprise. Built for senior and staff software engineers preparing for rigorous coding screens at top tech companies (FAANG/MAMAA).

13 Core Algorithmic Patterns & 225 Practice Problems

  • 1. Two Pointers (16 Paradigms, 43 Problems): Opposite ends, sorted pair sums, palindrome verification, trapping rain water, 3Sum, container with most water — includes the Sliding Window and Fast & Slow Pointers paradigms (contiguous subarray invariants, longest substrings, Floyd's cycle detection, linked list middle).
  • 2. Binary Search (9 Paradigms, 14 Problems): Monotonic predicate partitioning (feasible(x)), boundary search, rotated sorted arrays, square roots, minimum ship capacity, median of two sorted arrays, matrix median on value range.
  • 3. Bit Manipulation (5 Paradigms, 11 Problems): Counting set bits, XOR cancellation, bit reversal, bitmask pairing, maximum XOR with a bitwise trie.
  • 4. Math & Geometry (8 Paradigms, 14 Problems): Sieve of Eratosthenes, integer/roman conversions, modular arithmetic, geometric simulation.
  • 5. Tree/Graph Depth-First Search (15 Paradigms, 24 Problems): Path sums, lowest common ancestor, tree diameter, validating BSTs, tree DP (House Robber III, Binary Tree Cameras).
  • 6. Tree/Graph Breadth-First Search (5 Paradigms, 12 Problems): Level-order traversals, shortest path in unweighted graphs, zig-zag traversals, rotting oranges, word ladders.
  • 7. Graphs (12 Paradigms, 22 Problems): Topological sort, cycle detection, Dijkstra's algorithm, bipartite graph validation, network delay.
  • 8. Backtracking (6 Paradigms, 14 Problems): Subsets, permutations, combinations, constraint satisfaction, pruning, N-Queens, Sudoku solver.
  • 9. Dynamic Programming (13 Paradigms, 28 Problems): Memoization vs tabulation, 0/1 knapsack, unbounded knapsack, coin change, edit distance, longest common subsequence.
  • 10. Heap / Priority Queue (9 Paradigms, 11 Problems): Running medians, top-k elements, interval scheduling, IPO, k-way merges.
  • 11. Advanced Data Structures (7 Paradigms, 17 Problems): Trie (prefix tree), Union-Find (Disjoint Set Union), LRU Cache, LFU Cache, range-sum queries with updates.
  • 12. Stack (5 Paradigms, 9 Problems): Next greater element, largest rectangle in histogram, remove k digits, decode string, min stack.
  • 13. Intervals & Greedy (2 Paradigms, 6 Problems): Merge intervals, interval scheduling, meeting rooms by sweep line, jump game.

4-Stage Deliberate Practice Framework

  1. Stage 1 (Compare & Learn): Read the pattern's mental model, loop invariant and Big-O proof, compare the pattern's template with the problem's solution side by side, and use the step-by-step debugger. The solution can also be shown in C#, Java, TypeScript, C++, Go or Rust for almost every problem.
  2. Stage 2 (Active Recall): Rebuild the solution from memory in a code editor, with an invariant checklist and optional progressive hints, and check it against a judged test suite.
  3. Stage 3 (AI Interview Coach, coming soon): A mock-interview stage still in development; for now, students go straight from Stage 2 to Stage 4.
  4. Stage 4 (Solve on Your Own): Solve a new problem on your own against a 15-minute timer; your code is graded against a test suite. Python and TypeScript run in your browser and C# runs on our server (design problems grade in Python and TypeScript).

Equipped with a spaced-repetition review hub on a fixed 7-step schedule (1 day up to 90 days), a two-pane Studio workspace, and study notes.

Pricing, Access & Commercial Terms

  • Core Curriculum: 100% Free. No credit card required.
  • Coins: New accounts get 40 free coins once, the daily claim adds +20 coins once a day, and inviting a friend earns you +25 coins when they complete their first practice step. These are the only ways to earn coins.
  • AI Coach: Each AI coach question costs 1-5 coins, priced by the server according to its size.
  • BYOK (Bring Your Own Key): AI coaching is free with your own Google Gemini, OpenAI or OpenRouter API key (BYOK).
  • Extras: Coins also unlock extras for 24 hours: a Recall hint level (1 coin), a Solve solution reveal (2), a LeetCode problem card's solutions (1) and a pattern's extra canonical problems (1).
  • Payments & Refunds: Nothing on the site is sold for money: coins can only be earned, never bought. There are no subscriptions or charges, so there is nothing to refund.
  • Platform Operator: Hi👋WebEnterprise. Support & policies at hispeedalgo.com.
Skip to main content
Hi👋SpeedAlgo

Invariant-First Algorithmic Mastery

Arena
238Items
Theory Context•Dynamic Programming

Builds on Kadane's Algorithm, which you haven’t finished yet.

P2MediumBuilt on Linear DP~4 min speedrun

Kadane's Algorithm with a Direction (Longest Turbulent Subarray)

Built on
Kadane's AlgorithmA run grows only when its next step goes the opposite way, so keep one length per direction of the last step, up and down, and flip them on each step.
The problem

Longest Turbulent Subarray (LC 978)(opens leetcode.com)

You get an integer array arr. A subarray is a run of numbers that sit next to each other. A subarray is turbulent when its steps alternate: every step goes up or down, and each step goes the other way from the step before it.

Return the length of the longest turbulent subarray. A single number is a turbulent subarray of length 1.

Example 1
Input:arr = [9,4,2,10,7,8,8,1,9]
Output:5
The subarray [4, 2, 10, 7, 8] goes down, up, down, up. The equal pair 8, 8 ends it, and [8, 1, 9] has length 3.

Turbulent Subarray

up, down = longest run ending here with a last step up or down ➔ a step up extends down, a step down extends up ➔ keep the best
Spot it when: You need the longest unbroken run of an array where each step goes the opposite way from the step before it.
Turbulent Subarray
Python
1def max_turbulence_size(arr: list[int]) -> int:
2 """Longest Turbulent Subarray: the longest run whose steps alternate between up and down.
3 Time: O(N) | Space: O(1)
4 """
5 # up, down: the length of the longest turbulent subarray ending at the current number whose last step went up, or went down; best: the longest seen
6 up = down = best = 1
7 for i in range(1, len(arr)):
8 # 1. Flip The Direction Or Restart:
9 # A step up extends the run whose last step went down, a step down extends the run whose last step went up, and an equal step restarts both.
10 if arr[i] > arr[i - 1]:
11 up, down = down + 1, 1
12 elif arr[i] < arr[i - 1]:
13 up, down = 1, up + 1
14 else:
15 up = down = 1
16 
17 # 2. Track The Best:
18 # Every turbulent subarray ends at some index, so the largest length seen at any index is the answer.
19 best = max(best, up, down)
20 
21 return best
Invariant: After each step from arr[i - 1] to arr[i], up and down are the lengths of the longest turbulent subarray ending at arr[i] whose last step went up or down, and best is the largest of both seen so far.

A run is turbulent only if each step goes the other way from the step before it, so the state must remember the direction of the last step: up and down are the longest turbulent runs ending here whose last step went up or down. A step up gives up, down = down + 1, 1, a step down gives up, down = 1, up + 1, and an equal step is neither, so it gives up = down = 1. The trap is the direction: a step up extends down, not up, because extending up counts two steps up in a row.

See it run

Longest Turbulent Subarray, step by step

up 1 · down 1 · best 1

up 1 · down 2 · best 2

up 1 · down 2 · best 2

up 3 · down 1 · best 3

up 1 · down 4 · best 4

up 5 · down 1 · best 5

up 1 · down 1 · best 5

up 1 · down 2 · best 5

up 3 · down 1 · best 5

up 3 · down 1 · best 5

Each column is one index of arr. The rows up and down fill in as the steps run.

  • arr[i] the number being read
  • arr[i - 1] the number before it
  • up the longest turbulent run that ends with a step up
  • down the longest turbulent run that ends with a step down

Start: up = down = best = 1. A single number is a run of length 1.

4 < 9: the step goes down, so down = old up + 1 = 1 + 1 = 2. up restarts at 1. Then best = 2.

2 < 4: the step goes down, so down = old up + 1 = 1 + 1 = 2. up restarts at 1. Then best = 2.

10 > 2: the step goes up, so up = old down + 1 = 2 + 1 = 3. down restarts at 1. Then best = 3.

7 < 10: the step goes down, so down = old up + 1 = 3 + 1 = 4. up restarts at 1. Then best = 4.

8 > 7: the step goes up, so up = old down + 1 = 4 + 1 = 5. down restarts at 1. Then best = 5.

8 = 8: the step is equal, so no turbulent run can cross it. up and down both restart at 1. Then best = 5.

1 < 8: the step goes down, so down = old up + 1 = 1 + 1 = 2. up restarts at 1. Then best = 5.

9 > 1: the step goes up, so up = old down + 1 = 2 + 1 = 3. down restarts at 1. Then best = 5.

Done: best = 5, the largest value that up or down reached.

arr
09arr[i]
14
22
310
47
58
68
71
89
up
1up
down
1down
1 / 10
Gotchas1 of 3

Gotcha 1 of 3

  1. 1
    The trap

    Gotcha 1: Extending the same direction

    Mistake
    up, down = up + 1, 1
    Fix
    up, down = down + 1, 1

    What happens: A step up must follow a step down, so it extends the run whose last step went down. Extending up adds a second step up in a row to the run, and a run with two steps up in a row is not turbulent.

    Example: Longest Turbulent Subarray (LC 978): arr = [4, 8, 12, 16]
    Mistake: returns 4Fix: returns 2
  2. 2

    Gotcha 2: Treating an equal step as a step down

    Mistake
    up, down = 1, up + 1
    Fix
    up = down = 1

    What happens: Equal neighbours are neither up nor down. If the else branch continues the run as a step down, a pair of equal numbers is counted as a step, and the run grows across it.

    Example: Longest Turbulent Subarray (LC 978): arr = [9, 9]
    Mistake: returns 2Fix: returns 1
  3. 3

    Gotcha 3: Keeping only the run that ended with a step up

    Mistake
    best = max(best, up)
    Fix
    best = max(best, up, down)

    What happens: The longest run can end with a step down. best must take both lengths. With up only, an array whose longest turbulent run ends with a step down never counts that run.

    Example: Longest Turbulent Subarray (LC 978): arr = [3, 2]
    Mistake: returns 1Fix: returns 2
Not this one if…
  • A run grows with any next number, so one length is enough and the direction of the last step does not matter, as in Maximum Subarray (LC 53). See Kadane's Algorithm

Deep Dive

Why one length is not enough

A subarray is turbulent when its steps alternate: up, then down, then up, and so on, or the reverse. A step is up when arr[i] > arr[i - 1] and down when arr[i] < arr[i - 1].

In Kadane's Algorithm, a run can grow with any next number. Here a run can grow only if the next step goes the opposite way from the last step of the run. So the run's length alone is not a complete state. The state must also say which way the last step went.

The card keeps two lengths for the subarrays that end at arr[i]. up is the longest turbulent subarray whose last step went up. down is the longest one whose last step went down. The lengths count numbers, so a single number has length 1.

Why the update flips the lengths

Suppose the step from arr[i - 1] to arr[i] goes up. A turbulent subarray can end with this step only if the step before it went down. So the new up is the old down plus 1. The old down is the longest subarray ending at arr[i - 1] with a last step down.

A subarray cannot end at arr[i] with a last step down, because the step into arr[i] went up. So the new down is 1, which is arr[i] alone.

A step down is the mirror image: up, down = 1, up + 1. An equal step is neither up nor down, so no run can cross it. Both lengths restart at 1.

The tuple assignment reads the old up and down on the right side, so the flip is safe.

Trace and the cost

Trace for arr = [9, 4, 2, 10, 7, 8, 8, 1, 9], as arr[i], up, down, best:

  • 4, 1, 2, 2.
  • 2, 1, 2, 2.
  • 10, 3, 1, 3.
  • 7, 1, 4, 4.
  • 8, 5, 1, 5.
  • 8, 1, 1, 5.
  • 1, 1, 2, 5.
  • 9, 3, 1, 5.

The answer is 5, from the run [4, 2, 10, 7, 8]. The steps are down, up, down, up.

There are N - 1 steps, and each does constant work. The time is O(N) and the space is O(1).

Edge cases: an array with one number returns 1. An array of equal numbers returns 1. A strictly increasing array such as [4, 8, 12, 16] returns 2, because only one step in a row can be part of a turbulent run.

A related problem with a different state

Longest Mountain in Array (LC 845) also depends on the direction of steps. But a mountain does not alternate. It rises, and then it falls, once. The state is the phase (rising or falling), and a rise after a fall ends the mountain.

So the common idea is only this: when the next step depends on the last step, the state must store the last step's direction.

60-Second Pitch

"A run is turbulent when each step goes the opposite way from the step before it. So the state must remember the direction of the last step. I keep up and down, the longest turbulent runs that end here with a last step up or down. A step up gives up, down = down + 1, 1. A step down gives up, down = 1, up + 1. An equal step sets both to 1. I keep the largest value of either in best. The time is O(N) and the space is O(1)."

Common Questions

Why does a step up extend down and not up?

A turbulent run alternates. A run that ends with a step up can only be extended by a step down. In the same way, a new step up must come after a run whose last step went down, so it extends down. Extending up would put two steps up in a row.

What happens with equal neighbours?

An equal step is neither up nor down, so no turbulent run can contain it. Both up and down restart at 1. For [9, 9], the answer is 1.

What is the time and space complexity?

O(N) time, because there are N - 1 steps and each does constant work. O(1) space, because only up, down and best exist.

What is the answer for a strictly increasing array?

2, when the array has at least two numbers. Every step goes up, so a run can hold only one step. For [4, 8, 12, 16], the answer is 2. For one number, the answer is 1.

How does Longest Mountain in Array (LC 845) differ?

A mountain rises and then falls once. It does not alternate. The state is the phase, rising or falling, and a new rise after a fall ends the mountain. The idea of storing the last step's direction is shared, but the update rules are different.

SWE Reasoning

Spot it

  • The question asks for the longest unbroken run that follows a rule about the direction of each step.
  • The rule compares each step with the step before it, not each number with a fixed value.
  • Equal neighbours break the run.
  • A brute force checks every start and end in O(N^2) or more.
  • One length per position is not enough, because the next step depends on how the last step went.

The invariant, step by step

  1. Before the loop, up, down and best are all 1. One number is a turbulent subarray of length 1.
  2. For each i, compare arr[i] with arr[i - 1].
  3. If the step goes up, up becomes the old down plus 1, and down becomes 1.
  4. If the step goes down, down becomes the old up plus 1, and up becomes 1.
  5. If the numbers are equal, both become 1.
  6. best = max(best, up, down) keeps the longest length seen. After the loop, best is the answer.

Traps

  • Same direction. up + 1 after a step up counts two steps up in a row. For [4, 8, 12, 16], the result is 4 instead of 2.
  • Equal step treated as a direction. Equal neighbours are neither up nor down. For [9, 9], the result is 2 instead of 1.
  • Using only one length for best. The longest run can end with either direction. For [3, 2], using up only gives 1 instead of 2.
  • Starting at 0. A single number is a run of length 1. For [100], the answer is 1.
  • Two separate assignments. Writing up = down + 1 and then down = up + 1 uses the new up. Use one tuple assignment.

Practice

Canonical LeetCode:Longest Turbulent Subarray (LC 978)Longest Mountain in Array (LC 845)
Theory Context•Dynamic Programming

Builds on Kadane's Algorithm, which you haven’t finished yet.

P2MediumBuilt on Linear DP~4 min speedrun

Kadane's Algorithm with a Direction (Longest Turbulent Subarray)

Built on
Kadane's AlgorithmA run grows only when its next step goes the opposite way, so keep one length per direction of the last step, up and down, and flip them on each step.
The problem

Longest Turbulent Subarray (LC 978)(opens leetcode.com)

You get an integer array arr. A subarray is a run of numbers that sit next to each other. A subarray is turbulent when its steps alternate: every step goes up or down, and each step goes the other way from the step before it.

Return the length of the longest turbulent subarray. A single number is a turbulent subarray of length 1.

Example 1
Input:arr = [9,4,2,10,7,8,8,1,9]
Output:5
The subarray [4, 2, 10, 7, 8] goes down, up, down, up. The equal pair 8, 8 ends it, and [8, 1, 9] has length 3.

Turbulent Subarray

up, down = longest run ending here with a last step up or down ➔ a step up extends down, a step down extends up ➔ keep the best
Spot it when: You need the longest unbroken run of an array where each step goes the opposite way from the step before it.
Turbulent Subarray
Python
1def max_turbulence_size(arr: list[int]) -> int:
2 """Longest Turbulent Subarray: the longest run whose steps alternate between up and down.
3 Time: O(N) | Space: O(1)
4 """
5 # up, down: the length of the longest turbulent subarray ending at the current number whose last step went up, or went down; best: the longest seen
6 up = down = best = 1
7 for i in range(1, len(arr)):
8 # 1. Flip The Direction Or Restart:
9 # A step up extends the run whose last step went down, a step down extends the run whose last step went up, and an equal step restarts both.
10 if arr[i] > arr[i - 1]:
11 up, down = down + 1, 1
12 elif arr[i] < arr[i - 1]:
13 up, down = 1, up + 1
14 else:
15 up = down = 1
16 
17 # 2. Track The Best:
18 # Every turbulent subarray ends at some index, so the largest length seen at any index is the answer.
19 best = max(best, up, down)
20 
21 return best
Invariant: After each step from arr[i - 1] to arr[i], up and down are the lengths of the longest turbulent subarray ending at arr[i] whose last step went up or down, and best is the largest of both seen so far.

A run is turbulent only if each step goes the other way from the step before it, so the state must remember the direction of the last step: up and down are the longest turbulent runs ending here whose last step went up or down. A step up gives up, down = down + 1, 1, a step down gives up, down = 1, up + 1, and an equal step is neither, so it gives up = down = 1. The trap is the direction: a step up extends down, not up, because extending up counts two steps up in a row.

See it run

Longest Turbulent Subarray, step by step

up 1 · down 1 · best 1

up 1 · down 2 · best 2

up 1 · down 2 · best 2

up 3 · down 1 · best 3

up 1 · down 4 · best 4

up 5 · down 1 · best 5

up 1 · down 1 · best 5

up 1 · down 2 · best 5

up 3 · down 1 · best 5

up 3 · down 1 · best 5

Each column is one index of arr. The rows up and down fill in as the steps run.

  • arr[i] the number being read
  • arr[i - 1] the number before it
  • up the longest turbulent run that ends with a step up
  • down the longest turbulent run that ends with a step down

Start: up = down = best = 1. A single number is a run of length 1.

4 < 9: the step goes down, so down = old up + 1 = 1 + 1 = 2. up restarts at 1. Then best = 2.

2 < 4: the step goes down, so down = old up + 1 = 1 + 1 = 2. up restarts at 1. Then best = 2.

10 > 2: the step goes up, so up = old down + 1 = 2 + 1 = 3. down restarts at 1. Then best = 3.

7 < 10: the step goes down, so down = old up + 1 = 3 + 1 = 4. up restarts at 1. Then best = 4.

8 > 7: the step goes up, so up = old down + 1 = 4 + 1 = 5. down restarts at 1. Then best = 5.

8 = 8: the step is equal, so no turbulent run can cross it. up and down both restart at 1. Then best = 5.

1 < 8: the step goes down, so down = old up + 1 = 1 + 1 = 2. up restarts at 1. Then best = 5.

9 > 1: the step goes up, so up = old down + 1 = 2 + 1 = 3. down restarts at 1. Then best = 5.

Done: best = 5, the largest value that up or down reached.

arr
09arr[i]
14
22
310
47
58
68
71
89
up
1up
down
1down
1 / 10
Gotchas1 of 3

Gotcha 1 of 3

  1. 1
    The trap

    Gotcha 1: Extending the same direction

    Mistake
    up, down = up + 1, 1
    Fix
    up, down = down + 1, 1

    What happens: A step up must follow a step down, so it extends the run whose last step went down. Extending up adds a second step up in a row to the run, and a run with two steps up in a row is not turbulent.

    Example: Longest Turbulent Subarray (LC 978): arr = [4, 8, 12, 16]
    Mistake: returns 4Fix: returns 2
  2. 2

    Gotcha 2: Treating an equal step as a step down

    Mistake
    up, down = 1, up + 1
    Fix
    up = down = 1

    What happens: Equal neighbours are neither up nor down. If the else branch continues the run as a step down, a pair of equal numbers is counted as a step, and the run grows across it.

    Example: Longest Turbulent Subarray (LC 978): arr = [9, 9]
    Mistake: returns 2Fix: returns 1
  3. 3

    Gotcha 3: Keeping only the run that ended with a step up

    Mistake
    best = max(best, up)
    Fix
    best = max(best, up, down)

    What happens: The longest run can end with a step down. best must take both lengths. With up only, an array whose longest turbulent run ends with a step down never counts that run.

    Example: Longest Turbulent Subarray (LC 978): arr = [3, 2]
    Mistake: returns 1Fix: returns 2
Not this one if…
  • A run grows with any next number, so one length is enough and the direction of the last step does not matter, as in Maximum Subarray (LC 53). See Kadane's Algorithm

Deep Dive

Why one length is not enough

A subarray is turbulent when its steps alternate: up, then down, then up, and so on, or the reverse. A step is up when arr[i] > arr[i - 1] and down when arr[i] < arr[i - 1].

In Kadane's Algorithm, a run can grow with any next number. Here a run can grow only if the next step goes the opposite way from the last step of the run. So the run's length alone is not a complete state. The state must also say which way the last step went.

The card keeps two lengths for the subarrays that end at arr[i]. up is the longest turbulent subarray whose last step went up. down is the longest one whose last step went down. The lengths count numbers, so a single number has length 1.

Why the update flips the lengths

Suppose the step from arr[i - 1] to arr[i] goes up. A turbulent subarray can end with this step only if the step before it went down. So the new up is the old down plus 1. The old down is the longest subarray ending at arr[i - 1] with a last step down.

A subarray cannot end at arr[i] with a last step down, because the step into arr[i] went up. So the new down is 1, which is arr[i] alone.

A step down is the mirror image: up, down = 1, up + 1. An equal step is neither up nor down, so no run can cross it. Both lengths restart at 1.

The tuple assignment reads the old up and down on the right side, so the flip is safe.

Trace and the cost

Trace for arr = [9, 4, 2, 10, 7, 8, 8, 1, 9], as arr[i], up, down, best:

  • 4, 1, 2, 2.
  • 2, 1, 2, 2.
  • 10, 3, 1, 3.
  • 7, 1, 4, 4.
  • 8, 5, 1, 5.
  • 8, 1, 1, 5.
  • 1, 1, 2, 5.
  • 9, 3, 1, 5.

The answer is 5, from the run [4, 2, 10, 7, 8]. The steps are down, up, down, up.

There are N - 1 steps, and each does constant work. The time is O(N) and the space is O(1).

Edge cases: an array with one number returns 1. An array of equal numbers returns 1. A strictly increasing array such as [4, 8, 12, 16] returns 2, because only one step in a row can be part of a turbulent run.

A related problem with a different state

Longest Mountain in Array (LC 845) also depends on the direction of steps. But a mountain does not alternate. It rises, and then it falls, once. The state is the phase (rising or falling), and a rise after a fall ends the mountain.

So the common idea is only this: when the next step depends on the last step, the state must store the last step's direction.

60-Second Pitch

"A run is turbulent when each step goes the opposite way from the step before it. So the state must remember the direction of the last step. I keep up and down, the longest turbulent runs that end here with a last step up or down. A step up gives up, down = down + 1, 1. A step down gives up, down = 1, up + 1. An equal step sets both to 1. I keep the largest value of either in best. The time is O(N) and the space is O(1)."

Common Questions

Why does a step up extend down and not up?

A turbulent run alternates. A run that ends with a step up can only be extended by a step down. In the same way, a new step up must come after a run whose last step went down, so it extends down. Extending up would put two steps up in a row.

What happens with equal neighbours?

An equal step is neither up nor down, so no turbulent run can contain it. Both up and down restart at 1. For [9, 9], the answer is 1.

What is the time and space complexity?

O(N) time, because there are N - 1 steps and each does constant work. O(1) space, because only up, down and best exist.

What is the answer for a strictly increasing array?

2, when the array has at least two numbers. Every step goes up, so a run can hold only one step. For [4, 8, 12, 16], the answer is 2. For one number, the answer is 1.

How does Longest Mountain in Array (LC 845) differ?

A mountain rises and then falls once. It does not alternate. The state is the phase, rising or falling, and a new rise after a fall ends the mountain. The idea of storing the last step's direction is shared, but the update rules are different.

SWE Reasoning

Spot it

  • The question asks for the longest unbroken run that follows a rule about the direction of each step.
  • The rule compares each step with the step before it, not each number with a fixed value.
  • Equal neighbours break the run.
  • A brute force checks every start and end in O(N^2) or more.
  • One length per position is not enough, because the next step depends on how the last step went.

The invariant, step by step

  1. Before the loop, up, down and best are all 1. One number is a turbulent subarray of length 1.
  2. For each i, compare arr[i] with arr[i - 1].
  3. If the step goes up, up becomes the old down plus 1, and down becomes 1.
  4. If the step goes down, down becomes the old up plus 1, and up becomes 1.
  5. If the numbers are equal, both become 1.
  6. best = max(best, up, down) keeps the longest length seen. After the loop, best is the answer.

Traps

  • Same direction. up + 1 after a step up counts two steps up in a row. For [4, 8, 12, 16], the result is 4 instead of 2.
  • Equal step treated as a direction. Equal neighbours are neither up nor down. For [9, 9], the result is 2 instead of 1.
  • Using only one length for best. The longest run can end with either direction. For [3, 2], using up only gives 1 instead of 2.
  • Starting at 0. A single number is a run of length 1. For [100], the answer is 1.
  • Two separate assignments. Writing up = down + 1 and then down = up + 1 uses the new up. Use one tuple assignment.

Practice

Canonical LeetCode:Longest Turbulent Subarray (LC 978)Longest Mountain in Array (LC 845)
© 2026 Hi👋WebEnterprise. All rights reserved.
Sitemap•llms.txt•