LeetCode 594 - Longest Harmonious Subsequence


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.
https://discuss.leetcode.com/topic/89990/simple-java-hashmap-solution
  • The idea is to keep a count of all the numbers, and eventually for each of the numbers, check if there's any adjacent number. If it's present, then add the count of both - since these two numbers form subsequence in the array.
Update : from @harkness comment, we don't need to check both +1 and -1;
Any reason to use long instead of int?
to handle this :
findLHS(new int[]{-2147483648 , 2147483647});
//2147483647 + 1 = -2147483648 , and we don't want that.
public int findLHS(int[] nums) {
    Map<Long, Integer> map = new HashMap<>();
    for (long num : nums) {
        map.put(num, map.getOrDefault(num, 0) + 1);
    }
    int result = 0;
    for (long key : map.keySet()) {
        if (map.containsKey(key + 1)) {
            result = Math.max(result, map.get(key + 1) + map.get(key));
        }
    }
    return result;
}

http://bookshadow.com/weblog/2017/05/21/leetcode-longest-harmonious-subsequence/
用字典cnt统计各数字出现的次数。
升序遍历cnt的键值对
X. https://discuss.leetcode.com/topic/90049/simple-java-sort-solution-beat-100
public int findLHS(int[] nums) {
    if (nums.length == 0) {
        return 0;
    }
    Arrays.sort(nums);
    int start = 0;
    int min = nums[0];
    int res = 0;
    int nextstart = 1;
    for (int i = 1; i < nums.length; i++) {
        if (nums[i] - min > 1) {
            start = nextstart++;
            min = nums[start];
            i--;
        } else if (nums[i] - min == 1) {
            res = Math.max(res, i - start + 1);
            if (nums[i] != nums[i - 1]) {
                nextstart = i;
            }
        }
    }
    return res;
}
X. https://discuss.leetcode.com/topic/90049/simple-java-sort-solution-beat-100
public int findLHS(int[] nums) {
    if (nums.length == 0) {
        return 0;
    }
    Arrays.sort(nums);
    int start = 0;
    int min = nums[0];
    int res = 0;
    int nextstart = 1;
    for (int i = 1; i < nums.length; i++) {
        if (nums[i] - min > 1) {
            start = nextstart++;
            min = nums[start];
            i--;
        } else if (nums[i] - min == 1) {
            res = Math.max(res, i - start + 1);
            if (nums[i] != nums[i - 1]) {
                nextstart = i;
            }
        }
    }
    return res;
}

https://medium.com/@xingren14/594-longest-harmonious-subsequence-94c93f83a4af
首先这个是subsequence,所以其实原数组的顺序已经不重要了,或者说顺序根本不是考察的范围所能用得到的,所以我们要么可以排序再分析,要么就是利用HashMap来统计频率,这也是我知道的两个解法的始源
先说排序的算法:
  1. 排序了,然后怎么分析呢?一开始想的是直接遍历然后看是不是比前一个大一或者相等。我擦这么明显的错误都能犯?不是检测是不是递增,而是相差1的子数组相当于,否则连[1,2,3]这样的数组都不过测试。那就增加个临时变量表示之前的数字?还是不对因为这样还需要回溯,但是又回到哪里去呢?我们只设一个指针来遍历是不够的。那么我们用俩
  2. 两个指针其实就是我们最喜闻乐见的sliding window了。但是这个sliding window又稍微有些不一样。 一般siliding window是超出范围后结算的。但是这道题怎么说是“超出范围”呢?如果我们是决定num[right] 比 num[left] 大超过1是超出范围应该结算的话,那么这个test case就不对了:[1,1,1,4] 这个应该返回0,但是会被错误地返回3。 思来想去这道题的关键是当出现rigth比left的值大1的时候,我们才可以自信的说我们有harmonious subsequence,因为如果是1 1 1 1 或者 1,3,5,8都是不行的。
  3. 于是结算就不是发现窗口扩展不下去了再结算,而是每次只要有效都要结算。动态增加而不是最后结算。这样每次看到right比left的值大1就更新下res并right++。其他如果right比left大于超过1。left++,否则(其实也就是等于1) right++。

再说HashMap,这个思路完全不一样,先遍历数组统计各数字的频率,然后再遍历一次来看每个数字是否其+1和-1的数也在hashmap里,如果在就把俩人的freq的和跟res比,谁大要谁。然后将当前数字从map里删掉以免重复比较。
这个思路很简单而且只需要O(n)的时间和O(n)的space。但是其运行速度却比上一个要慢了50%,为什么呢?我能想到的就是hashmap的查找和增删时间的消耗。



Labels

LeetCode (1432) GeeksforGeeks (1122) LeetCode - Review (1067) Review (882) Algorithm (668) to-do (609) Classic Algorithm (270) Google Interview (237) Classic Interview (222) Dynamic Programming (220) DP (186) Bit Algorithms (145) POJ (141) Math (137) Tree (132) LeetCode - Phone (129) EPI (122) Cracking Coding Interview (119) DFS (115) Difficult Algorithm (115) Lintcode (115) Different Solutions (110) Smart Algorithm (104) Binary Search (96) BFS (91) HackerRank (90) Binary Tree (86) Hard (79) Two Pointers (78) Stack (76) Company-Facebook (75) BST (72) Graph Algorithm (72) Time Complexity (69) Greedy Algorithm (68) Interval (63) Company - Google (62) Geometry Algorithm (61) Interview Corner (61) LeetCode - Extended (61) Union-Find (60) Trie (58) Advanced Data Structure (56) List (56) Priority Queue (53) Codility (52) ComProGuide (50) LeetCode Hard (50) Matrix (50) Bisection (48) Segment Tree (48) Sliding Window (48) USACO (46) Space Optimization (45) Company-Airbnb (41) Greedy (41) Mathematical Algorithm (41) Tree - Post-Order (41) ACM-ICPC (40) Algorithm Interview (40) Data Structure Design (40) Graph (40) Backtracking (39) Data Structure (39) Jobdu (39) Random (39) Codeforces (38) Knapsack (38) LeetCode - DP (38) Recursive Algorithm (38) String Algorithm (38) TopCoder (38) Sort (37) Introduction to Algorithms (36) Pre-Sort (36) Beauty of Programming (35) Must Known (34) Binary Search Tree (33) Follow Up (33) prismoskills (33) Palindrome (32) Permutation (31) Array (30) Google Code Jam (30) HDU (30) Array O(N) (29) Logic Thinking (29) Monotonic Stack (29) Puzzles (29) Code - Detail (27) Company-Zenefits (27) Microsoft 100 - July (27) Queue (27) Binary Indexed Trees (26) TreeMap (26) to-do-must (26) 1point3acres (25) GeeksQuiz (25) Merge Sort (25) Reverse Thinking (25) hihocoder (25) Company - LinkedIn (24) Hash (24) High Frequency (24) Summary (24) Divide and Conquer (23) Proof (23) Game Theory (22) Topological Sort (22) Lintcode - Review (21) Tree - Modification (21) Algorithm Game (20) CareerCup (20) Company - Twitter (20) DFS + Review (20) DP - Relation (20) Brain Teaser (19) DP - Tree (19) Left and Right Array (19) O(N) (19) Sweep Line (19) UVA (19) DP - Bit Masking (18) LeetCode - Thinking (18) KMP (17) LeetCode - TODO (17) Probabilities (17) Simulation (17) String Search (17) Codercareer (16) Company-Uber (16) Iterator (16) Number (16) O(1) Space (16) Shortest Path (16) itint5 (16) DFS+Cache (15) Dijkstra (15) Euclidean GCD (15) Heap (15) LeetCode - Hard (15) Majority (15) Number Theory (15) Rolling Hash (15) Tree Traversal (15) Brute Force (14) Bucket Sort (14) DP - Knapsack (14) DP - Probability (14) Difficult (14) Fast Power Algorithm (14) Pattern (14) Prefix Sum (14) TreeSet (14) Algorithm Videos (13) Amazon Interview (13) Basic Algorithm (13) Codechef (13) Combination (13) Computational Geometry (13) DP - Digit (13) LCA (13) LeetCode - DFS (13) Linked List (13) Long Increasing Sequence(LIS) (13) Math-Divisible (13) Reservoir Sampling (13) mitbbs (13) Algorithm - How To (12) Company - Microsoft (12) DP - Interval (12) DP - Multiple Relation (12) DP - Relation Optimization (12) LeetCode - Classic (12) Level Order Traversal (12) Prime (12) Pruning (12) Reconstruct Tree (12) Thinking (12) X Sum (12) AOJ (11) Bit Mask (11) Company-Snapchat (11) DP - Space Optimization (11) Dequeue (11) Graph DFS (11) MinMax (11) Miscs (11) Princeton (11) Quick Sort (11) Stack - Tree (11) 尺取法 (11) 挑战程序设计竞赛 (11) Coin Change (10) DFS+Backtracking (10) Facebook Hacker Cup (10) Fast Slow Pointers (10) HackerRank Easy (10) Interval Tree (10) Limited Range (10) Matrix - Traverse (10) Monotone Queue (10) SPOJ (10) Starting Point (10) States (10) Stock (10) Theory (10) Tutorialhorizon (10) Kadane - Extended (9) Mathblog (9) Max-Min Flow (9) Maze (9) Median (9) O(32N) (9) Quick Select (9) Stack Overflow (9) System Design (9) Tree - Conversion (9) Use XOR (9) Book Notes (8) Company-Amazon (8) DFS+BFS (8) DP - States (8) Expression (8) Longest Common Subsequence(LCS) (8) One Pass (8) Quadtrees (8) Traversal Once (8) Trie - Suffix (8) 穷竭搜索 (8) Algorithm Problem List (7) All Sub (7) Catalan Number (7) Cycle (7) DP - Cases (7) Facebook Interview (7) Fibonacci Numbers (7) Flood fill (7) Game Nim (7) Graph BFS (7) HackerRank Difficult (7) Hackerearth (7) Inversion (7) Kadane’s Algorithm (7) Manacher (7) Morris Traversal (7) Multiple Data Structures (7) Normalized Key (7) O(XN) (7) Radix Sort (7) Recursion (7) Sampling (7) Suffix Array (7) Tech-Queries (7) Tree - Serialization (7) Tree DP (7) Trie - Bit (7) 蓝桥杯 (7) Algorithm - Brain Teaser (6) BFS - Priority Queue (6) BFS - Unusual (6) Classic Data Structure Impl (6) DP - 2D (6) DP - Monotone Queue (6) DP - Unusual (6) DP-Space Optimization (6) Dutch Flag (6) How To (6) Interviewstreet (6) Knapsack - MultiplePack (6) Local MinMax (6) MST (6) Minimum Spanning Tree (6) Number - Reach (6) Parentheses (6) Pre-Sum (6) Probability (6) Programming Pearls (6) Rabin-Karp (6) Reverse (6) Scan from right (6) Schedule (6) Stream (6) Subset Sum (6) TSP (6) Xpost (6) n00tc0d3r (6) reddit (6) AI (5) Abbreviation (5) Anagram (5) Art Of Programming-July (5) Assumption (5) Bellman Ford (5) Big Data (5) Code - Solid (5) Code Kata (5) Codility-lessons (5) Coding (5) Company - WMware (5) Convex Hull (5) Crazyforcode (5) DFS - Multiple (5) DFS+DP (5) DP - Multi-Dimension (5) DP-Multiple Relation (5) Eulerian Cycle (5) Graph - Unusual (5) Graph Cycle (5) Hash Strategy (5) Immutability (5) Java (5) LogN (5) Manhattan Distance (5) Matrix Chain Multiplication (5) N Queens (5) Pre-Sort: Index (5) Quick Partition (5) Quora (5) Randomized Algorithms (5) Resources (5) Robot (5) SPFA(Shortest Path Faster Algorithm) (5) Shuffle (5) Sieve of Eratosthenes (5) Strongly Connected Components (5) Subarray Sum (5) Sudoku (5) Suffix Tree (5) Swap (5) Threaded (5) Tree - Creation (5) Warshall Floyd (5) Word Search (5) jiuzhang (5)

Popular Posts