← Back to Cheat Sheets
Kadane
Table of Contents
- # 0) Concept
- # 0-1) Types
- # 0-2) Algorithm Pattern / Template
- # 1) Example Problems
- # 2) Implementation Variants
- # 2-1) Classic Kadane’s (LC 53)
- # 2-2) With Index Tracking
- # 2-3) Maximum Product Subarray (LC 152)
- # 2-4) Circular Maximum Subarray (LC 918)
- # 3) Tips & Pitfalls
- # ✅ Tips & Optimizations
- # ❌ Common Mistakes
- # Space vs Time Tradeoffs
- # Key Insights
- # Related Patterns
# KADANE ALGORITHM
- Core idea: Find maximum sum of contiguous subarray in O(n) time using dynamic programming approach
- When to use it: Maximum subarray sum, optimization problems on arrays, sliding window maximum sum
- Key LeetCode problems: LC 53, LC 152, LC 918, LC 1186
- Data structures commonly used: Array, variables to track current/global max
- Typical states: Current maximum ending here vs global maximum so far
# 0) Concept
# 0-1) Types
- Maximum Subarray Sum: Classic Kadane’s algorithm (LC 53)
- Maximum Product Subarray: Modified for multiplication (LC 152)
- Circular Array Maximum: Handle wraparound cases (LC 918)
- Maximum with At Most One Deletion: Allow removing one element (LC 1186)
- 2D Kadane’s: Extended to matrices for maximum rectangle sum
# 0-2) Algorithm Pattern / Template
Basic Kadane’s Algorithm:
def kadane(nums):
if not nums:
return 0
current_max = global_max = nums[0]
for i in range(1, len(nums)):
# At each position: extend current subarray OR start new subarray
current_max = max(nums[i], current_max + nums[i])
global_max = max(global_max, current_max)
return global_max
Key Decision at Each Step:
current_max = max(nums[i], current_max + nums[i])nums[i]: Start new subarray from current elementcurrent_max + nums[i]: Extend existing subarray
Important Edge Cases:
- All negative numbers → return the maximum single element
- Empty array → handle based on problem requirements
- Single element → return that element
# 1) Example Problems
- LC 53 – Maximum Subarray (Classic Kadane’s - find maximum sum of contiguous subarray)
- LC 152 – Maximum Product Subarray (Track both max and min products due to negative numbers)
- LC 918 – Maximum Sum Circular Subarray (Handle circular array with two cases: normal max vs circular max)
- LC 1186 – Maximum Subarray Sum with One Deletion (Allow deleting at most one element)
- LC 121 – Best Time to Buy and Sell Stock (Maximum difference/profit subarray problem)
- LC 1191 – K-Concatenation Maximum Sum (Kadane’s on concatenated arrays)
# 2) Implementation Variants
# 2-1) Classic Kadane’s (LC 53)
def maxSubArray(nums):
current_sum = max_sum = nums[0]
for i in range(1, len(nums)):
current_sum = max(nums[i], current_sum + nums[i])
max_sum = max(max_sum, current_sum)
return max_sum
# 2-2) With Index Tracking
def maxSubArrayWithIndices(nums):
current_sum = max_sum = nums[0]
start = end = temp_start = 0
for i in range(1, len(nums)):
if current_sum < 0:
current_sum = nums[i]
temp_start = i
else:
current_sum += nums[i]
if current_sum > max_sum:
max_sum = current_sum
start = temp_start
end = i
return max_sum, start, end
# 2-3) Maximum Product Subarray (LC 152)
def maxProduct(nums):
if not nums:
return 0
max_prod = min_prod = result = nums[0]
for i in range(1, len(nums)):
if nums[i] < 0:
# Swap max and min when multiplying by negative
max_prod, min_prod = min_prod, max_prod
max_prod = max(nums[i], max_prod * nums[i])
min_prod = min(nums[i], min_prod * nums[i])
result = max(result, max_prod)
return result
# 2-4) Circular Maximum Subarray (LC 918)
def maxSubarraySumCircular(nums):
def kadane(arr):
current = maximum = arr[0]
for i in range(1, len(arr)):
current = max(arr[i], current + arr[i])
maximum = max(maximum, current)
return maximum
# Case 1: Maximum subarray is normal (non-circular)
max_normal = kadane(nums)
# Case 2: Maximum subarray is circular
# Circular max = Total sum - minimum subarray
total_sum = sum(nums)
# Find minimum subarray (negate array and find max)
negated = [-x for x in nums]
max_negated = kadane(negated)
min_subarray = -max_negated
max_circular = total_sum - min_subarray
# Edge case: if all numbers are negative
if max_circular == 0:
return max_normal
return max(max_normal, max_circular)
# 3) Tips & Pitfalls
# ✅ Tips & Optimizations
- Reset Strategy: When
current_sumbecomes negative, reset to current element - Space Optimization: Only need O(1) extra space, no need for DP array
- Negative Numbers: Handle all-negative arrays by returning maximum single element
- Product Variants: Track both maximum and minimum for multiplication problems
- Circular Arrays: Consider both normal and circular cases separately
# ❌ Common Mistakes
- Forgetting Edge Cases: Not handling empty arrays or single elements
- All Negative Arrays: Incorrectly returning 0 instead of maximum element
- Product Problems: Not tracking minimum values (important when multiplying negatives)
- Index Tracking: Off-by-one errors when tracking start/end positions
- Circular Arrays: Missing the edge case where minimum subarray equals total array
# Space vs Time Tradeoffs
- Time: O(n) - single pass through array
- Space: O(1) - only need few variables
- When to use DP array: If you need to reconstruct the actual subarray or track intermediate states
# Key Insights
- At each position, decide: “Should I extend the current subarray or start fresh?”
- Current sum < 0 means starting fresh is better
- Global maximum tracks the best subarray seen so far
- For products: negative numbers can turn small values into large ones (track min/max)
# Related Patterns
- Sliding Window: When dealing with fixed-size subarrays
- Prefix Sum: When dealing with range sum queries
- Dynamic Programming: Kadane’s is essentially 1D DP optimization