LeetCode 594: Longest Harmonious Subsequence Solution in Python – A Step-by-Step Guide

Imagine you’re handed an array of numbers—like [1, 3, 2, 2, 5, 2, 3, 7]—and your task is to find the longest stretch of elements you can pick where the biggest and smallest numbers differ by exactly 1, such as selecting [3, 2, 2, 2, 3] for a length of 5. That’s the intriguing challenge of LeetCode 594: Longest Harmonious Subsequence, an easy-to-medium problem that’s a fantastic way to practice array manipulation in Python. We’ll explore two solutions: the Best Solution, a hash map with frequency counting that’s efficient and clever, and an Alternative Solution, a brute-force subsequence check that’s thorough but less practical. With detailed examples, clear code, and a friendly tone—especially for the hash map approach—this guide will help you find that harmonious stretch, whether you’re new to coding or leveling up. Let’s count those frequencies and start searching!

What Is LeetCode 594: Longest Harmonious Subsequence?

Section link icon

In LeetCode 594: Longest Harmonious Subsequence, you’re given an integer array nums, and your task is to return the length of the longest harmonious subsequence—a subsequence where the difference between the maximum and minimum values is exactly 1. A subsequence can be formed by picking elements in any order without changing their relative positions’ continuity requirement (unlike a subarray). For example, with nums = [1,3,2,2,5,2,3,7], the longest harmonious subsequence is [3,2,2,2,3] (length 5), as max (3) - min (2) = 1. This problem builds on LeetCode 1: Two Sum for hash map usage but focuses on finding maximum subsequence lengths with a specific difference constraint.

Problem Statement

  • Input: nums (List[int])—array of integers.
  • Output: Integer—length of longest harmonious subsequence.
  • Rules: Subsequence max - min = 1; elements can be non-contiguous; return 0 if no such subsequence exists.

Constraints

  • 1 <= nums.length <= 2 * 10⁴
  • -10⁹ <= nums[i] <= 10⁹

Examples

  • Input: nums = [1,3,2,2,5,2,3,7]
    • Output: 5
    • Subsequence [3,2,2,2,3], max=3, min=2, length=5.
  • Input: nums = [1,2,3,4]
    • Output: 2
    • Subsequence [1,2] or [2,3] or [3,4], length=2.
  • Input: nums = [1,1,1,1]
    • Output: 0
    • No pair differs by 1.

Understanding the Problem: Finding the Harmonious Stretch

Section link icon

To solve LeetCode 594: Longest Harmonious Subsequence in Python, we need to find the longest subsequence in an array where the maximum and minimum values differ by exactly 1, handling up to 2 * 10⁴ elements efficiently. A brute-force approach checking all possible subsequences (O(2^n)) is impractical. Instead, a key insight—only consecutive integers (e.g., x and x+1) can form a harmonious subsequence—leads to a hash map solution that counts frequencies in O(n) time, checking pairs of consecutive numbers. We’ll explore:

  • Best Solution (Hash Map with Frequency Counting): O(n) time, O(n) space—fast and optimal.
  • Alternative Solution (Brute-Force Subsequence Checking): O(2^n) time, O(n) space—thorough but slow.

Let’s dive into the hash map solution with a friendly breakdown!

Best Solution: Hash Map with Frequency Counting

Section link icon

Why Hash Map Wins

The hash map with frequency counting solution is the best for LeetCode 594 because it finds the longest harmonious subsequence in O(n) time and O(n) space by building a frequency map of all numbers in one pass, then checking each number and its consecutive pair (x and x+1) to compute the maximum length efficiently. It’s like tallying votes for each number, then pairing neighbors to see who teams up best—all in a quick, clever count!

How It Works

Think of this as a number-pairing organizer:

  • Step 1: Build Frequency Map:
    • Use a hash map to count occurrences of each number in nums.
  • Step 2: Check Consecutive Pairs:
    • For each number x in the map:
      • If x+1 exists, compute length = freq(x) + freq(x+1).
      • Update maximum length if larger.
  • Step 3: Return Result:
    • Maximum length found (0 if no pairs).
  • Why It Works:
    • Harmonious subsequence must be two consecutive integers.
    • Hash map enables O(1) frequency lookups.

It’s like a harmonious-pairing maestro!

Step-by-Step Example

Example: nums = [1,3,2,2,5,2,3,7]

  • Step 1: Build frequency map:
    • freq = {1: 1, 2: 3, 3: 2, 5: 1, 7: 1}.
  • Step 2: Check pairs:
    • 1: 1+1=2 exists, length = 1 + 3 = 4.
    • 2: 2+1=3 exists, length = 3 + 2 = 5.
    • 3: 3+1=4 not present, skip.
    • 5: 5+1=6 not present, skip.
    • 7: 7+1=8 not present, skip.
    • Max length = 5 (pair 2 and 3).
  • Step 3: Return 5.
  • Result: 5.

Example: nums = [1,2,3,4]

  • Step 1: freq = {1: 1, 2: 1, 3: 1, 4: 1}.
  • Step 2:
    • 1: 1+1=2, length = 1 + 1 = 2.
    • 2: 2+1=3, length = 1 + 1 = 2.
    • 3: 3+1=4, length = 1 + 1 = 2.
    • 4: 4+1=5, skip.
    • Max length = 2.
  • Step 3: Return 2.
  • Result: 2.

Code with Detailed Line-by-Line Explanation

Here’s the Python code, explained for beginners:

class Solution:
    def findLHS(self, nums: List[int]) -> int:
        # Step 1: Build frequency map
        freq = {}
        for num in nums:
            freq[num] = freq.get(num, 0) + 1

        # Step 2: Find max length of harmonious subsequence
        max_length = 0
        for x in freq:
            if x + 1 in freq:
                length = freq[x] + freq[x + 1]
                max_length = max(max_length, length)

        # Step 3: Return result
        return max_length
  • Lines 4-6: Initialize hash map, count frequency of each number.
  • Lines 9-13: Iterate map:
    • Check if x+1 exists, compute length, update max.
  • Line 16: Return longest harmonious length.
  • Time Complexity: O(n)—single pass to build map and check pairs.
  • Space Complexity: O(n)—hash map storage.

It’s like a frequency-pairing wizard!

Alternative Solution: Brute-Force Subsequence Checking

Section link icon

Why an Alternative Approach?

The brute-force subsequence checking approach generates all possible subsequences, checks each for the harmonious property (max - min = 1), and tracks the longest, running in O(2^n) time and O(n) space for recursion or storage. It’s thorough but impractical for large arrays, making it a good baseline for small inputs or understanding.

How It Works

Picture this as a subsequence-hunting brute:

  • Step 1: Generate all subsequences (recursively or iteratively).
  • Step 2: For each, compute max and min, check if difference is 1.
  • Step 3: Track longest valid subsequence.
  • Step 4: Return length.

It’s like a trial-and-error harmony seeker!

Step-by-Step Example

Example: nums = [1,2,3]

  • Step 1: Subsequences: [1], [2], [3], [1,2], [1,3], [2,3], [1,2,3].
  • Step 2: Check:
    • [1,2]: 2-1=1, length=2.
    • [2,3]: 3-2=1, length=2.
    • Others: Difference ≠ 1 or length < 2.
  • Step 3: Max length = 2.
  • Result: 2.

Code for Brute-Force Approach

class Solution:
    def findLHS(self, nums: List[int]) -> int:
        def is_harmonious(sub):
            if not sub:
                return False
            min_val, max_val = min(sub), max(sub)
            return max_val - min_val == 1

        def generate_subsequences(arr, index, curr, all_subs):
            if index == len(arr):
                if curr:
                    all_subs.append(curr[:])
                return
            # Exclude current element
            generate_subsequences(arr, index + 1, curr, all_subs)
            # Include current element
            curr.append(arr[index])
            generate_subsequences(arr, index + 1, curr, all_subs)
            curr.pop()

        # Generate all subsequences
        all_subs = []
        generate_subsequences(nums, 0, [], all_subs)

        # Find longest harmonious subsequence
        max_length = 0
        for sub in all_subs:
            if is_harmonious(sub):
                max_length = max(max_length, len(sub))

        return max_length
  • Lines 3-7: Check if subsequence is harmonious.
  • Lines 9-18: Recursively generate all subsequences.
  • Lines 21-22: Build subsequence list.
  • Lines 25-28: Find longest valid subsequence.
  • Time Complexity: O(2^n)—exponential subsequence generation.
  • Space Complexity: O(n)—recursion stack and storage.

It’s a brute-force harmony hunter!

Comparing the Two Solutions

Section link icon
  • Hash Map (Best):
    • Pros: O(n), O(n), fast and elegant.
    • Cons: Requires frequency insight.
  • Brute-Force (Alternative):
    • Pros: O(2^n), O(n), exhaustive.
    • Cons: Impractical for large n.

Hash map wins for efficiency!

Additional Examples and Edge Cases

Section link icon
  • Single value: 0.
  • No pairs: 0.
  • All same: 0.

Hash map handles them all!

Complexity Recap

Section link icon
  • Hash Map: Time O(n), Space O(n).
  • Brute-Force: Time O(2^n), Space O(n).

Hash map’s the speed champ!

Key Takeaways

Section link icon
  • Hash Map: Frequency finesse—learn at Python Basics!
  • Brute-Force: Exhaustive search.
  • Subsequences: Harmony is fun.
  • Python: Map or brute, your pick!

Final Thoughts: Find That Harmony!

Section link icon

LeetCode 594: Longest Harmonious Subsequence in Python is a clever array challenge. Hash map with frequency counting is your fast track, while brute-force offers a thorough dive. Want more? Try LeetCode 1: Two Sum or LeetCode 560: Subarray Sum Equals K. Ready to count? Head to Solve LeetCode 594 on LeetCode and find that harmonious stretch today!