Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
Program to find largest sum of non-adjacent elements of a list in Python
The problem of finding the largest sum of non-adjacent elements in a list is a classic dynamic programming problem. Given a list of numbers, we need to select elements such that no two selected elements are adjacent, and their sum is maximized.
So, if the input is like [3, 5, 7, 3, 6], then the output will be 16, as we can take 3, 7, and 6 to get the maximum sum without selecting adjacent elements.
Algorithm Approach
We use dynamic programming with two variables to track the maximum sum:
take: Maximum sum including the current element
noTake: Maximum sum excluding the current element
For each element, we decide whether to include it or not based on which choice gives the maximum sum.
Implementation
def find_max_sum_non_adjacent(nums):
if len(nums) <= 2:
return max(nums) if nums else 0
noTake = 0
take = nums[0]
for i in range(1, len(nums)):
# Current element can be taken with previous noTake sum
# Or we can skip current element and keep previous max
take, noTake = noTake + nums[i], max(noTake, take)
return max(noTake, take)
# Test with example
nums = [3, 5, 7, 3, 6]
result = find_max_sum_non_adjacent(nums)
print(f"Maximum sum of non-adjacent elements: {result}")
Maximum sum of non-adjacent elements: 16
How It Works
Let's trace through the algorithm with [3, 5, 7, 3, 6]:
def find_max_sum_detailed(nums):
if len(nums) <= 2:
return max(nums) if nums else 0
noTake = 0
take = nums[0]
print(f"Initial: take={take}, noTake={noTake}")
for i in range(1, len(nums)):
old_take, old_noTake = take, noTake
take = noTake + nums[i]
noTake = max(old_noTake, old_take)
print(f"i={i}, nums[i]={nums[i]}: take={take}, noTake={noTake}")
return max(noTake, take)
nums = [3, 5, 7, 3, 6]
result = find_max_sum_detailed(nums)
print(f"Final result: {result}")
Initial: take=3, noTake=0 i=1, nums[i]=5: take=5, noTake=3 i=2, nums[i]=7: take=10, noTake=5 i=3, nums[i]=3: take=8, noTake=10 i=4, nums[i]=6: take=16, noTake=10 Final result: 16
Testing with Different Cases
def test_cases():
test_data = [
([3, 5, 7, 3, 6], 16),
([1, 2, 3], 4),
([5, 1, 3, 9], 14),
([2, 1], 2),
([0, -1, 2], 2),
([10], 10)
]
for nums, expected in test_data:
result = find_max_sum_non_adjacent(nums)
status = "?" if result == expected else "?"
print(f"{status} {nums} ? {result} (expected: {expected})")
test_cases()
? [3, 5, 7, 3, 6] ? 16 (expected: 16) ? [1, 2, 3] ? 4 (expected: 4) ? [5, 1, 3, 9] ? 14 (expected: 14) ? [2, 1] ? 2 (expected: 2) ? [0, -1, 2] ? 2 (expected: 2) ? [10] ? 10 (expected: 10)
Time and Space Complexity
Time Complexity: O(n) - single pass through the array
Space Complexity: O(1) - only two variables used
Conclusion
This dynamic programming solution efficiently finds the maximum sum of non-adjacent elements using constant space. The key insight is maintaining two states: taking or not taking the current element, and choosing the optimal decision at each step.
