githubEdit

17. Max Sum Increasing Subsequence

βœ… GFG solution to the Max Sum Increasing Subsequence problem: find maximum sum of strictly increasing subsequence using dynamic programming and optimized approaches. πŸš€

The problem can be found at the following link: πŸ”— Question Linkarrow-up-right

🧩 Problem Description

You are given an array arr[] consisting of positive integers. Your task is to find the maximum sum of a subsequence such that the elements of the subsequence form a strictly increasing sequence.

In other words, among all strictly increasing subsequences of the array, return the one with the largest possible sum.

πŸ“˜ Examples

Example 1

Input: arr[] = [1, 101, 2, 3, 100]
Output: 106
Explanation: The maximum sum of an increasing sequence is obtained from [1, 2, 3, 100].

Example 2

Input: arr[] = [4, 1, 2, 3]
Output: 6
Explanation: The maximum sum of an increasing sequence is obtained from [1, 2, 3].

Example 3

πŸ”’ Constraints

  • $1 \le \text{arr.size()} \le 10^3$

  • $1 \le \text{arr}[i] \le 10^5$

βœ… My Approach

The optimal approach uses Dynamic Programming to efficiently build up the maximum sum for increasing subsequences ending at each position:

Dynamic Programming Approach

  1. Initialize DP Array:

    • Create a dp[] array where dp[i] represents the maximum sum of increasing subsequence ending at index i.

    • Initially, set dp[i] = arr[i] as each element can form a subsequence by itself.

  2. Build DP Table:

    • For each position i, iterate through all previous positions j (where j < i).

    • If arr[j] < arr[i] (strictly increasing condition), update dp[i] = max(dp[i], dp[j] + arr[i]).

    • This means we can extend the subsequence ending at j by including arr[i].

  3. Track Maximum:

    • Maintain a variable res to track the maximum value in the dp[] array.

    • Update res after computing each dp[i].

  4. Return Result:

    • The answer is the maximum value in the dp[] array, representing the largest sum achievable.

πŸ“ Time and Auxiliary Space Complexity

  • Expected Time Complexity: O(nΒ²), where n is the size of the array. We use nested loops to compare each element with all previous elements to build the DP table.

  • Expected Auxiliary Space Complexity: O(n), as we use a DP array of size n to store the maximum sum ending at each position.

πŸ§‘β€πŸ’» Code (C++)

chevron-right⚑ View Alternative Approaches with Code and Analysishashtag

πŸ“Š 2️⃣ TreeMap-Based Approach

πŸ’‘ Algorithm Steps:

  1. Use a TreeMap to maintain the maximum sum for each value encountered.

  2. For each element, find the best sum from all smaller elements using lower_bound.

  3. Update the map with the new sum and remove redundant entries.

  4. Track the maximum sum throughout the process.

πŸ“ Complexity Analysis:

  • Time: ⏱️ O(n log n) - TreeMap operations for each element

  • Auxiliary Space: πŸ’Ύ O(n) - Space for map storage

βœ… Why This Approach?

  • Efficient for large value ranges

  • Automatically maintains sorted order

  • Prunes suboptimal solutions dynamically

πŸ“Š 3️⃣ Binary Indexed Tree Approach

πŸ’‘ Algorithm Steps:

  1. Coordinate compress array values to handle large ranges.

  2. Use BIT to query maximum sum ending at values less than current.

  3. Update BIT with new maximum sum at current value position.

  4. Return the maximum sum found across all updates.

πŸ“ Complexity Analysis:

  • Time: ⏱️ O(n log n) - Sorting and BIT operations

  • Auxiliary Space: πŸ’Ύ O(n) - BIT and coordinate arrays

βœ… Why This Approach?

  • Handles duplicates efficiently

  • Scalable for competitive programming

  • Clean separation of concerns

πŸ“Š 4️⃣ Segment Tree Approach

πŸ’‘ Algorithm Steps:

  1. Compress coordinates to map values to indices.

  2. Build segment tree to maintain maximum sums for ranges.

  3. Query maximum sum for all values less than current element.

  4. Update segment tree with current element's maximum sum.

πŸ“ Complexity Analysis:

  • Time: ⏱️ O(n log n) - Coordinate compression and segment tree queries

  • Auxiliary Space: πŸ’Ύ O(n) - Segment tree storage

βœ… Why This Approach?

  • Powerful for range queries

  • Extensible to more complex problems

  • Industry-standard data structure

πŸ†š πŸ” Comparison of Approaches

πŸš€ Approach

⏱️ Time Complexity

πŸ’Ύ Space Complexity

βœ… Pros

⚠️ Cons

🏷️ Dynamic Programming

🟑 O(n²)

🟒 O(n)

πŸ“– Simple and intuitive

🐌 Slower for large inputs

🌳 TreeMap-Based

🟒 O(n log n)

🟑 O(n)

⚑ Fast with optimization

πŸ”§ Complex logic

πŸ“Š Binary Indexed Tree

🟒 O(n log n)

🟑 O(n)

🎯 Efficient queries

🧩 Requires compression

πŸ”Ί Segment Tree

🟒 O(n log n)

🟑 O(n)

πŸ’ͺ Versatile structure

πŸ”¨ Implementation heavy

πŸ† Best Choice Recommendation

🎯 Scenario

πŸŽ–οΈ Recommended Approach

πŸ”₯ Performance Rating

πŸ… Small arrays (n ≀ 1000)

πŸ₯‡ Dynamic Programming

β˜…β˜…β˜…β˜…β˜…

πŸ“– Large arrays with optimization

πŸ₯ˆ TreeMap-Based

β˜…β˜…β˜…β˜…β˜…

πŸ”§ Competitive programming

πŸ₯‰ Binary Indexed Tree

β˜…β˜…β˜…β˜…β˜†

🎯 Complex range queries needed

πŸ… Segment Tree

β˜…β˜…β˜…β˜…β˜†

β˜• Code (Java)

🐍 Code (Python)

🧠 Contribution and Support

For discussions, questions, or doubts related to this solution, feel free to connect on LinkedIn: πŸ“¬ Any Questions?arrow-up-right. Let's make this learning journey more collaborative!

⭐ If you find this helpful, please give this repository a star! ⭐


πŸ“Visitor Count

Visitor counter

Last updated