# 594. Longest Harmonious Subsequence

**<font color=red>难度: Easy</font>**

## 刷题内容

> 原题连接

* https://leetcode.com/problems/longest-harmonious-subsequence/

> 内容描述

```
We define a harmonious array is an array where the difference between its maximum value and its minimum value is exactly 1.

Now, given an integer array, you need to find the length of its longest harmonious subsequence among all its possible subsequences.

Example 1:
Input: [1,3,2,2,5,2,3,7]
Output: 5
Explanation: The longest harmonious subsequence is [3,2,2,2,3].
Note: The length of the input array will not exceed 20,000.
```

## 解题方案

> 思路 1
******- 时间复杂度: O(N)******- 空间复杂度: O(1)******

先排序，然后挨个算就可以了

beats 33.12%

```python
class Solution:
    def findLHS(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        if not nums or len(nums) == 0:
            return 0
        
        nums.sort()
        res = 0
        cur_cnt =  1 # Length of maximum value
        prev_cnt = 0 # Length of minimum value whose value is smaller by 1
        for i in range(1, len(nums)):
            if nums[i] == nums[i-1]:
                cur_cnt += 1
            elif nums[i] == nums[i-1] + 1:
                prev_cnt = cur_cnt
                cur_cnt = 1
            else:
                prev_cnt = 0
                cur_cnt = 1
            if prev_cnt:
                res = max(res, prev_cnt + cur_cnt)
        return res
```


> 思路 2
******- 时间复杂度: O(N)******- 空间复杂度: O(N)******

每种 num 要么是最大值，要么是最小值，且必须拥有另外一边的数字（即作为最大值时要有最小值出现，作为最小值时要有最大值出现）

先用Counter记下出现频率

beats 33.65%

```python
class Solution:
    def findLHS(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        if not nums or len(nums) == 0:
            return 0
        
        lookup = collections.Counter(nums)
        res = -sys.maxsize
        
        for num in set(nums):
            num_as_max = lookup[num]+lookup[num-1] if lookup[num-1] else 0
            num_as_min = lookup[num]+lookup[num+1] if lookup[num+1] else 0
            res = max(res, num_as_max, num_as_min)
            
        return res
```

但是仔细一想，这样相当于算了两遍，我们要么就一直把num当成最大值，要么一直当成最小值，这样一定可以算完所有数的

beats 66.56%

```python
class Solution:
    def findLHS(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        if not nums or len(nums) == 0:
            return 0
        
        lookup = collections.Counter(nums)
        res = -sys.maxsize
        
        for key in lookup:
            num_as_max = lookup[key]+lookup[key-1] if lookup[key-1] else 0
            res = max(res, num_as_max)
            
        return res
```

> 思路 3
******- 时间复杂度: O(N)******- 空间复杂度: O(N)******

还可以做到one pass,但是这样就跟我们最初的想法一样了，必须同时考虑 num 作为最大值和最小值的情况，只 beats 24.84% 可能是测试用例的原因

```python
class Solution:
    def findLHS(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        if not nums or len(nums) == 0:
            return 0
        
        res, lookup = 0, {}
        
        for num in nums:
            lookup[num] = lookup.get(num, 0) + 1
            if num + 1 in lookup:
                res = max(res, lookup[num]+lookup[num+1])
            if num - 1 in lookup:
                res = max(res, lookup[num]+lookup[num-1])
            
        return res
```
