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 on a Circular Array (Maximum Sum Circular Subarray)

Built on
Kadane's AlgorithmA run may wrap around the end, and that run is the total minus the worst plain run, so run Kadane a second time with min and keep the total.
The problem

Maximum Sum Circular Subarray (LC 918)(opens leetcode.com)

You get an integer array nums that is circular: the number after the last one is the first one again. A subarray is a run of numbers that sit next to each other, and it may wrap around the end.

Find the largest sum of a non-empty subarray. A subarray can use each position at most once.

Example 1
Input:nums = [1,-2,3,-2]
Output:3
The subarray [3] has the largest sum, 3.

Circular Kadane

best plain run, or total - worst plain run ➔ Kadane twice, once with max and once with min ➔ guard the all-negative array
Spot it when: You need the best sum of one unbroken run of a circular array, where the run may wrap around from the end to the start.
Circular Kadane
Python
1def max_subarray_circular(nums: list[int]) -> int:
2 """Maximum Sum Circular Subarray: the best plain run, or the total minus the worst plain run.
3 Time: O(N) | Space: O(1)
4 """
5 # best, worst: the best and the worst sum of a plain subarray; curr_max, curr_min: the same for one that ends at the current number
6 total = curr_max = curr_min = best = worst = nums[0]
7 for x in nums[1:]:
8 # 1. Run Kadane For The Best And For The Worst:
9 # The same extend-or-restart rule, once with max for the best run and once with min for the worst run.
10 curr_max = max(x, curr_max + x)
11 curr_min = min(x, curr_min + x)
12 best = max(best, curr_max)
13 worst = min(worst, curr_min)
14 total += x
15 
16 # 2. Choose The Plain Run Or The Wrapping Run:
17 # A run that wraps around is the total minus a plain run in the middle, so remove the worst plain run.
18 # If every number is negative, the worst plain run is the whole array and the wrapping run would be empty, so keep best.
19 return max(best, total - worst) if best > 0 else best
Invariant: After each x, best and worst are the best and the worst sum of a plain subarray so far, and total is the sum of the numbers seen.

A run in a circular array is a plain run, or it wraps around the end, and a wrapping run is the whole array without one plain run in the middle. So run Kadane's Algorithm twice, once with max for best and once with min for worst, keep total, and the answer is the larger of best and total - worst. The trap is an array of only negative numbers: worst is then the whole array, total - worst is 0, and that is an empty run, so return best when it is not positive.

See it run

Circular Kadane, step by step

curr_max -2 · curr_min -2 · best -2 · worst -2 · total -2

curr_max 4 · curr_min 2 · best 4 · worst -2 · total 2

curr_max -1 · curr_min -5 · best 4 · worst -5 · total -3

curr_max 4 · curr_min -1 · best 4 · worst -5 · total 1

curr_max -1 · curr_min -6 · best 4 · worst -6 · total -4

curr_max 9 · curr_min 3 · best 9 · worst -6 · total 5

curr_max 13 · curr_min 4 · best 13 · worst -6 · total 9

curr_max 13 · curr_min 4 · best 13 · worst -6 · total 9 · answer 15

Each column is one index of nums. The rows curr_max and curr_min fill in as the steps run.

  • x the number being read
  • curr_max the largest sum of a run that ends at x
  • curr_min the smallest sum of a run that ends at x

Start: total, curr_max, curr_min, best and worst are all nums[0] = -2.

x = 4: curr_max = 4 (restart at x) and curr_min = 2 (extend). Now best = 4, worst = -2 and total = 2.

x = -5: curr_max = -1 (extend) and curr_min = -5 (restart at x). Now best = 4, worst = -5 and total = -3.

x = 4: curr_max = 4 (restart at x) and curr_min = -1 (extend). Now best = 4, worst = -5 and total = 1.

x = -5: curr_max = -1 (extend) and curr_min = -6 (extend). Now best = 4, worst = -6 and total = -4.

x = 9: curr_max = 9 (restart at x) and curr_min = 3 (extend). Now best = 9, worst = -6 and total = 5.

x = 4: curr_max = 13 (extend) and curr_min = 4 (restart at x). Now best = 13, worst = -6 and total = 9.

Done: the plain run is best = 13, and the wrapping run is total - worst = 9 - (-6) = 15. The answer is max(13, 15) = 15.

nums
0-2x
14
2-5
34
4-5
59
64
curr_max
-2curr_max
curr_min
-2curr_min
1 / 8
Gotchas1 of 3

Gotcha 1 of 3

  1. 1
    The trap

    Gotcha 1: Taking total - worst when every number is negative

    Mistake
    return max(best, total - worst)
    Fix
    return max(best, total - worst) if best > 0 else best

    What happens: When every number is negative, the worst plain run is the whole array, so total - worst is 0. That would be an empty run, which is not allowed. The answer is the largest single number, which best already holds.

    Example: Maximum Sum Circular Subarray (LC 918): nums = [-3, -2, -3]
    Mistake: returns 0Fix: returns -2
  2. 2

    Gotcha 2: Removing the best run instead of the worst

    Mistake
    return max(best, total - best) if best > 0 else best
    Fix
    return max(best, total - worst) if best > 0 else best

    What happens: A wrapping run is everything except one plain run in the middle. To make the wrapping run as large as possible, remove the plain run with the smallest sum, the worst one. Removing the best run leaves the smallest piece.

    Example: Maximum Sum Circular Subarray (LC 918): nums = [5, -3, 5]
    Mistake: returns 7Fix: returns 10
  3. 3

    Gotcha 3: Returning only the best plain run

    Mistake
    return best
    Fix
    return max(best, total - worst) if best > 0 else best

    What happens: The best run may wrap around the end. A plain Kadane pass never joins the last numbers to the first ones, so it misses a run such as the two 5s around the -3.

    Example: Maximum Sum Circular Subarray (LC 918): nums = [5, -3, 5]
    Mistake: returns 7Fix: returns 10
Not this one if…
  • The array is not circular, so a run never wraps around the end and one Kadane pass is enough, as in Maximum Subarray (LC 53). See Kadane's Algorithm

Deep Dive

Why a wrapping run is the total minus a plain run

In a circular array, the last number is followed by the first number. A run can start near the end and continue at the start. Such a run wraps around.

Place the array on a circle and choose a run. The numbers that are not in the run form one unbroken piece of the circle. If the run wraps around the end of the list, that remaining piece lies inside the list, in the middle. It is a plain subarray.

So the sum of a wrapping run is total minus the sum of a plain run in the middle. To make the wrapping run as large as possible, remove the plain run with the smallest sum. That sum is worst.

Example: for nums = [5, -3, 5], total is 7 and worst is -3. The wrapping run has the sum 7 - (-3) = 10. It is the two 5s that touch at the wrap. A plain pass finds only 7.

Two Kadane passes in one loop

Maximum Subarray (LC 53) taught the extend-or-restart rule with max. The same rule with min gives the smallest sum of a subarray that ends at x. The blueprint keeps curr_max and curr_min, and it updates best and worst from them.

Both passes use the same loop, so the time stays O(N). total adds one more number per step. The space is O(1), with five variables.

The answer is max(best, total - worst). best covers the runs that do not wrap. total - worst covers the runs that wrap.

Trace for nums = [5, -3, 5]: best is 7, worst is -3 and total is 7. The answer is max(7, 10) = 10.

The empty run and the guard

If the removed plain run is the whole array, then total - worst is 0. That is an empty run, and a run must hold at least one number.

This happens when every number is negative. Then worst is the whole array. The correct answer is the largest single number, which is best.

The guard if best > 0 else best handles it. If best is positive, an empty run (value 0) can never be larger than best, so max(best, total - worst) is safe. If best is 0 or negative, return best.

Example: for [-3, -2, -3], total is -8, worst is -8, and the answer is -2. For the single number [-5], the answer is -5.

Checks and a related problem

I compared max_subarray_circular with a brute force that tries every start and every length on the circle. They agreed on 10,000 random arrays of 1 to 9 numbers, including arrays of only negative numbers and arrays of one number.

Example with a longer wrap: nums = [-2, 4, -5, 4, -5, 9, 4] has best = 13, worst = -6 and total = 9. The answer is max(13, 9 + 6) = 15. The run is 9, 4, -2, 4, which wraps around the end.

Maximum Absolute Sum of Any Subarray (LC 1749) uses the same two passes. The answer is max(best, -worst), because the absolute value of the smallest sum can be the largest.

60-Second Pitch

"A run in a circular array either stays inside the list or wraps around the end. If it wraps, the numbers outside the run form one plain piece in the middle. So a wrapping run is total minus a plain subarray, and the largest one removes the smallest plain subarray. I run Kadane's Algorithm twice in one loop, with max for best and with min for worst, and I add up total. The answer is max(best, total - worst). If every number is negative, total - worst is an empty run, so I return best. The time is O(N) and the space is O(1)."

Common Questions

Why does removing the smallest plain run give the best wrapping run?

A wrapping run is the whole circle without one plain run in the middle of the list. Its sum is total minus the sum of that plain run. To make the result as large as possible, remove the plain run with the smallest sum, which is worst.

What does the function return when every number is negative?

The largest single number, which is best. Then worst is the whole array, so total - worst is 0. That would be an empty run, which is not allowed. For [-3, -2, -3], the answer is -2.

What is the time and space complexity?

O(N) time, because one loop runs both Kadane passes and the total. O(1) space, because the function keeps five numbers.

What if the array has only one number?

The loop does not run. best, worst and total all equal nums[0]. If it is positive, total - worst is 0 and best wins. If it is not positive, the guard returns best. For [-5], the answer is -5.

How does Maximum Absolute Sum of Any Subarray (LC 1749) relate to this card?

It uses the same two Kadane passes without the total. The largest absolute sum is the larger of best and -worst. The array is not circular there, so no wrap-around case exists.

SWE Reasoning

Spot it

  • The question asks for the best sum of one unbroken run of an array.
  • The array is circular: the last number is followed by the first number.
  • Plain Kadane's Algorithm fails on a small example such as [5, -3, 5].
  • The numbers can be negative, so the whole array is not always the best run.
  • The answer is a sum or a similar value that can be computed as a total minus a middle part.

The invariant, step by step

  1. Before the loop, all five variables start at nums[0]. Only one subarray ends at index 0.
  2. For each x, curr_max and curr_min apply the extend-or-restart rule with max and with min.
  3. best keeps the largest curr_max and worst keeps the smallest curr_min. total adds x.
  4. After the loop, best is the best plain run and worst is the worst plain run.
  5. A run that wraps is total - worst. A run that does not wrap is best.
  6. If best is not positive, total - worst may be an empty run. In that case the function returns best.

Traps

  • Missing guard. When every number is negative, total - worst is 0, an empty run. For [-3, -2, -3], the result is 0 instead of -2. For [-5], it is 0 instead of -5.
  • Subtracting best and not worst. The wrapping run needs the smallest middle part removed. See the card's gotcha for [5, -3, 5].
  • Plain Kadane only. It never joins the end to the start.
  • Starting at 0. Starting best or worst at 0 allows an empty run. Start all variables at nums[0].

Practice

Canonical LeetCode:Maximum Sum Circular Subarray (LC 918)Maximum Absolute Sum of Any Subarray (LC 1749)
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 on a Circular Array (Maximum Sum Circular Subarray)

Built on
Kadane's AlgorithmA run may wrap around the end, and that run is the total minus the worst plain run, so run Kadane a second time with min and keep the total.
The problem

Maximum Sum Circular Subarray (LC 918)(opens leetcode.com)

You get an integer array nums that is circular: the number after the last one is the first one again. A subarray is a run of numbers that sit next to each other, and it may wrap around the end.

Find the largest sum of a non-empty subarray. A subarray can use each position at most once.

Example 1
Input:nums = [1,-2,3,-2]
Output:3
The subarray [3] has the largest sum, 3.

Circular Kadane

best plain run, or total - worst plain run ➔ Kadane twice, once with max and once with min ➔ guard the all-negative array
Spot it when: You need the best sum of one unbroken run of a circular array, where the run may wrap around from the end to the start.
Circular Kadane
Python
1def max_subarray_circular(nums: list[int]) -> int:
2 """Maximum Sum Circular Subarray: the best plain run, or the total minus the worst plain run.
3 Time: O(N) | Space: O(1)
4 """
5 # best, worst: the best and the worst sum of a plain subarray; curr_max, curr_min: the same for one that ends at the current number
6 total = curr_max = curr_min = best = worst = nums[0]
7 for x in nums[1:]:
8 # 1. Run Kadane For The Best And For The Worst:
9 # The same extend-or-restart rule, once with max for the best run and once with min for the worst run.
10 curr_max = max(x, curr_max + x)
11 curr_min = min(x, curr_min + x)
12 best = max(best, curr_max)
13 worst = min(worst, curr_min)
14 total += x
15 
16 # 2. Choose The Plain Run Or The Wrapping Run:
17 # A run that wraps around is the total minus a plain run in the middle, so remove the worst plain run.
18 # If every number is negative, the worst plain run is the whole array and the wrapping run would be empty, so keep best.
19 return max(best, total - worst) if best > 0 else best
Invariant: After each x, best and worst are the best and the worst sum of a plain subarray so far, and total is the sum of the numbers seen.

A run in a circular array is a plain run, or it wraps around the end, and a wrapping run is the whole array without one plain run in the middle. So run Kadane's Algorithm twice, once with max for best and once with min for worst, keep total, and the answer is the larger of best and total - worst. The trap is an array of only negative numbers: worst is then the whole array, total - worst is 0, and that is an empty run, so return best when it is not positive.

See it run

Circular Kadane, step by step

curr_max -2 · curr_min -2 · best -2 · worst -2 · total -2

curr_max 4 · curr_min 2 · best 4 · worst -2 · total 2

curr_max -1 · curr_min -5 · best 4 · worst -5 · total -3

curr_max 4 · curr_min -1 · best 4 · worst -5 · total 1

curr_max -1 · curr_min -6 · best 4 · worst -6 · total -4

curr_max 9 · curr_min 3 · best 9 · worst -6 · total 5

curr_max 13 · curr_min 4 · best 13 · worst -6 · total 9

curr_max 13 · curr_min 4 · best 13 · worst -6 · total 9 · answer 15

Each column is one index of nums. The rows curr_max and curr_min fill in as the steps run.

  • x the number being read
  • curr_max the largest sum of a run that ends at x
  • curr_min the smallest sum of a run that ends at x

Start: total, curr_max, curr_min, best and worst are all nums[0] = -2.

x = 4: curr_max = 4 (restart at x) and curr_min = 2 (extend). Now best = 4, worst = -2 and total = 2.

x = -5: curr_max = -1 (extend) and curr_min = -5 (restart at x). Now best = 4, worst = -5 and total = -3.

x = 4: curr_max = 4 (restart at x) and curr_min = -1 (extend). Now best = 4, worst = -5 and total = 1.

x = -5: curr_max = -1 (extend) and curr_min = -6 (extend). Now best = 4, worst = -6 and total = -4.

x = 9: curr_max = 9 (restart at x) and curr_min = 3 (extend). Now best = 9, worst = -6 and total = 5.

x = 4: curr_max = 13 (extend) and curr_min = 4 (restart at x). Now best = 13, worst = -6 and total = 9.

Done: the plain run is best = 13, and the wrapping run is total - worst = 9 - (-6) = 15. The answer is max(13, 15) = 15.

nums
0-2x
14
2-5
34
4-5
59
64
curr_max
-2curr_max
curr_min
-2curr_min
1 / 8
Gotchas1 of 3

Gotcha 1 of 3

  1. 1
    The trap

    Gotcha 1: Taking total - worst when every number is negative

    Mistake
    return max(best, total - worst)
    Fix
    return max(best, total - worst) if best > 0 else best

    What happens: When every number is negative, the worst plain run is the whole array, so total - worst is 0. That would be an empty run, which is not allowed. The answer is the largest single number, which best already holds.

    Example: Maximum Sum Circular Subarray (LC 918): nums = [-3, -2, -3]
    Mistake: returns 0Fix: returns -2
  2. 2

    Gotcha 2: Removing the best run instead of the worst

    Mistake
    return max(best, total - best) if best > 0 else best
    Fix
    return max(best, total - worst) if best > 0 else best

    What happens: A wrapping run is everything except one plain run in the middle. To make the wrapping run as large as possible, remove the plain run with the smallest sum, the worst one. Removing the best run leaves the smallest piece.

    Example: Maximum Sum Circular Subarray (LC 918): nums = [5, -3, 5]
    Mistake: returns 7Fix: returns 10
  3. 3

    Gotcha 3: Returning only the best plain run

    Mistake
    return best
    Fix
    return max(best, total - worst) if best > 0 else best

    What happens: The best run may wrap around the end. A plain Kadane pass never joins the last numbers to the first ones, so it misses a run such as the two 5s around the -3.

    Example: Maximum Sum Circular Subarray (LC 918): nums = [5, -3, 5]
    Mistake: returns 7Fix: returns 10
Not this one if…
  • The array is not circular, so a run never wraps around the end and one Kadane pass is enough, as in Maximum Subarray (LC 53). See Kadane's Algorithm

Deep Dive

Why a wrapping run is the total minus a plain run

In a circular array, the last number is followed by the first number. A run can start near the end and continue at the start. Such a run wraps around.

Place the array on a circle and choose a run. The numbers that are not in the run form one unbroken piece of the circle. If the run wraps around the end of the list, that remaining piece lies inside the list, in the middle. It is a plain subarray.

So the sum of a wrapping run is total minus the sum of a plain run in the middle. To make the wrapping run as large as possible, remove the plain run with the smallest sum. That sum is worst.

Example: for nums = [5, -3, 5], total is 7 and worst is -3. The wrapping run has the sum 7 - (-3) = 10. It is the two 5s that touch at the wrap. A plain pass finds only 7.

Two Kadane passes in one loop

Maximum Subarray (LC 53) taught the extend-or-restart rule with max. The same rule with min gives the smallest sum of a subarray that ends at x. The blueprint keeps curr_max and curr_min, and it updates best and worst from them.

Both passes use the same loop, so the time stays O(N). total adds one more number per step. The space is O(1), with five variables.

The answer is max(best, total - worst). best covers the runs that do not wrap. total - worst covers the runs that wrap.

Trace for nums = [5, -3, 5]: best is 7, worst is -3 and total is 7. The answer is max(7, 10) = 10.

The empty run and the guard

If the removed plain run is the whole array, then total - worst is 0. That is an empty run, and a run must hold at least one number.

This happens when every number is negative. Then worst is the whole array. The correct answer is the largest single number, which is best.

The guard if best > 0 else best handles it. If best is positive, an empty run (value 0) can never be larger than best, so max(best, total - worst) is safe. If best is 0 or negative, return best.

Example: for [-3, -2, -3], total is -8, worst is -8, and the answer is -2. For the single number [-5], the answer is -5.

Checks and a related problem

I compared max_subarray_circular with a brute force that tries every start and every length on the circle. They agreed on 10,000 random arrays of 1 to 9 numbers, including arrays of only negative numbers and arrays of one number.

Example with a longer wrap: nums = [-2, 4, -5, 4, -5, 9, 4] has best = 13, worst = -6 and total = 9. The answer is max(13, 9 + 6) = 15. The run is 9, 4, -2, 4, which wraps around the end.

Maximum Absolute Sum of Any Subarray (LC 1749) uses the same two passes. The answer is max(best, -worst), because the absolute value of the smallest sum can be the largest.

60-Second Pitch

"A run in a circular array either stays inside the list or wraps around the end. If it wraps, the numbers outside the run form one plain piece in the middle. So a wrapping run is total minus a plain subarray, and the largest one removes the smallest plain subarray. I run Kadane's Algorithm twice in one loop, with max for best and with min for worst, and I add up total. The answer is max(best, total - worst). If every number is negative, total - worst is an empty run, so I return best. The time is O(N) and the space is O(1)."

Common Questions

Why does removing the smallest plain run give the best wrapping run?

A wrapping run is the whole circle without one plain run in the middle of the list. Its sum is total minus the sum of that plain run. To make the result as large as possible, remove the plain run with the smallest sum, which is worst.

What does the function return when every number is negative?

The largest single number, which is best. Then worst is the whole array, so total - worst is 0. That would be an empty run, which is not allowed. For [-3, -2, -3], the answer is -2.

What is the time and space complexity?

O(N) time, because one loop runs both Kadane passes and the total. O(1) space, because the function keeps five numbers.

What if the array has only one number?

The loop does not run. best, worst and total all equal nums[0]. If it is positive, total - worst is 0 and best wins. If it is not positive, the guard returns best. For [-5], the answer is -5.

How does Maximum Absolute Sum of Any Subarray (LC 1749) relate to this card?

It uses the same two Kadane passes without the total. The largest absolute sum is the larger of best and -worst. The array is not circular there, so no wrap-around case exists.

SWE Reasoning

Spot it

  • The question asks for the best sum of one unbroken run of an array.
  • The array is circular: the last number is followed by the first number.
  • Plain Kadane's Algorithm fails on a small example such as [5, -3, 5].
  • The numbers can be negative, so the whole array is not always the best run.
  • The answer is a sum or a similar value that can be computed as a total minus a middle part.

The invariant, step by step

  1. Before the loop, all five variables start at nums[0]. Only one subarray ends at index 0.
  2. For each x, curr_max and curr_min apply the extend-or-restart rule with max and with min.
  3. best keeps the largest curr_max and worst keeps the smallest curr_min. total adds x.
  4. After the loop, best is the best plain run and worst is the worst plain run.
  5. A run that wraps is total - worst. A run that does not wrap is best.
  6. If best is not positive, total - worst may be an empty run. In that case the function returns best.

Traps

  • Missing guard. When every number is negative, total - worst is 0, an empty run. For [-3, -2, -3], the result is 0 instead of -2. For [-5], it is 0 instead of -5.
  • Subtracting best and not worst. The wrapping run needs the smallest middle part removed. See the card's gotcha for [5, -3, 5].
  • Plain Kadane only. It never joins the end to the start.
  • Starting at 0. Starting best or worst at 0 allows an empty run. Start all variables at nums[0].

Practice

Canonical LeetCode:Maximum Sum Circular Subarray (LC 918)Maximum Absolute Sum of Any Subarray (LC 1749)
© 2026 Hi👋WebEnterprise. All rights reserved.
Sitemap•llms.txt•