Longest Harmonious Subsequence(#594)

Category: Array, Hash Map, Sliding Window, Sorting, Frequency Count, Two Pointer

๐Ÿงฉ Problem Statement

We define a harmonious array as one where the difference between the maximum and minimum element is exactly 1. Given an array `nums`, return the length of the longest harmonious subsequence you can find. A subsequence can be formed by deleting some or no elements without changing the order of the remaining elements.

๐Ÿ“š Examples

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

Output: 5

Explanation: The subsequence [2, 2, 2, 3, 3] is the longest harmonious subsequence.

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

Output: 2

Explanation: Both [1, 2] and [2, 3] are valid, so the max is 2.

Input: nums = [1, 1, 1, 1]

Output: 0

Explanation: No other number to pair with 1, so output is 0.

๐Ÿง  Approach

Approach 1:

Sliding Window (Brute Force)

โ€ข Sort the array.

โ€ข Use two pointers `start` and `end` to slide over the array.

โ€ข If the difference between nums[end] and nums[start] > 1, move `start` forward.

โ€ข If the difference is exactly 1, calculate the window length and update max.

Approach 2:

Optimized HashMap

โ€ข Build a frequency map of all numbers.

โ€ข For each number in the map, check if `num + 1` exists.

โ€ข If yes, add `map[num] + map[num + 1]` and update the result.

๐Ÿ’ป Code

// ๐Ÿ”น Approach 1: Brute Force (Using Sliding Window)
var findLHS = function(nums) {
  nums.sort((a, b) => a - b); // Sort the array
  let start = 0, maxLen = 0;

  for (let end = 0; end < nums.length; end++) {
    while (nums[end] - nums[start] > 1) {
      start++; // Shrink window if diff > 1
    }
    if (nums[end] - nums[start] === 1) {
      maxLen = Math.max(maxLen, end - start + 1); // Update max length
    }
  }

  return maxLen;
};

console.log(findLHS([1, 3, 2, 2, 5, 2, 3, 7])); // Output: 5
console.log(findLHS([1, 2, 3, 4])); // Output: 2


// ๐Ÿ”น Approach 2: Optimized (Using Hash Map)
var findLHS = function(nums) {
  const map = new Map();

  for (let num of nums) {
    map.set(num, (map.get(num) || 0) + 1); // Count frequency
  }

  let maxLen = 0;
  for (let [num, count] of map.entries()) {
    if (map.has(num + 1)) {
      maxLen = Math.max(maxLen, count + map.get(num + 1)); // Combine with neighbor
    }
  }

  return maxLen;
};

console.log(findLHS([1, 3, 2, 2, 5, 2, 3, 7])); // Output: 5
console.log(findLHS([1, 2, 3, 4])); // Output: 2

๐Ÿ“ˆ Complexity

Time: Brute Force: O(n log n) due to sorting. Optimized: O(n) using hash map.

Space: Brute Force: O(1) or O(n) (depends on sort). Optimized: O(n) for the frequency map.

๐ŸŽฌ Watch Explanation

๐Ÿ“Š Presentation (PPT)

๐Ÿ“ฅ Download PPT

๐Ÿ“Ž Resources