No.594 最长和谐子序列。难度:简单

和谐数组是指一个数组里元素的最大值和最小值之间的差别正好是1。

现在,给定一个整数数组,你需要在所有可能的子序列中找到最长的和谐子序列的长度。

示例 1:

输入: [1,3,2,2,5,2,3,7]

输出: 5

原因: 最长的和谐数组是:[3,2,2,2,3].

说明: 输入的数组长度最大不超过20,000.

思路一

关键点

  • 看到数组长度不超过20,000,说明穷举是肯定不会超时的
  • 只需要输出长度,意味着不需要记录子数组
  • 从示例来看,是不需要连续的
  • 差别正好是1,可以先设定一个数为n,去遍历nn+1的个数

实现

public int findLHS(int[] nums) {
    int max = 0;
    for(int i = 0; i < nums.length; i++){
        int num = 0;
        boolean diff = false;
        for(int j = 0; j < nums.length; j++){
            if(nums[i] == nums[j] || nums[i] + 1 == nums[j]){
                num++;
                if(nums[i] != nums[j]){
                    diff = true; // 如果数组全是一样的值,不能满足题目对于最大最小值正好相差1的描述
                }
            }
        }
        if(diff && num > max){
            max = num;
        }
    }
    return max;
}

时间复杂度$O(N^2)$,意料之中的垫底。

思路二

关键点

  • 遍历一次,将每个数字出现的次数记录在HashMap
  • 假设遍历的数字为n,写入HashMap的时候查看n-1n+1的出现次数,并取最大值

实现

public int findLHS(int[] nums) {
    int max = 0;
    Map<Integer, Integer> map = new HashMap<>();
    for(int i = 0; i < nums.length; i++){
        map.put(nums[i], map.getOrDefault(nums[i], 0) + 1);
        if(map.containsKey(nums[i] - 1)){
            max = Math.max(max, map.get(nums[i]) + map.get(nums[i] - 1));
        }
        if(map.containsKey(nums[i] + 1)){
            max = Math.max(max, map.get(nums[i]) + map.get(nums[i] + 1));
        }
    }
    return max;
}

时间复杂度$O(N)$,可是结果...

思路三

关键点

  • 大佬真多
  • 先进行排序,这样使用双指针就能进行单遍历了
  • 相差为01endIndex一直往后移动,超过1时把startIndex跳到上次endIndex增加的地方

实现

public int findLHS(int[] nums) {
    Arrays.sort(nums);
    int startIndex = 0;
    int endIndex = 0;
    int max = 0;
    int lastDiffIndex = 1;
    while(endIndex < nums.length){
        int start = nums[startIndex];
        int end = nums[endIndex];
        if(end - start == 0){
            endIndex++;
        }else if(end - start == 1){
            if(nums[lastDiffIndex] != end){
                lastDiffIndex = endIndex;
            }
            max = Math.max(max, endIndex - startIndex + 1);
            endIndex++;
        }else{
            startIndex = lastDiffIndex;
            lastDiffIndex = endIndex;
        }
    }
    return max;
}

时间复杂度也是$O(N)$,但是却少了很多操作HashMap的时间和判断次数。

结语

算法就是要追求极致,如果有更好更优美的实现方式,或者文中出现了错误,欢迎留言交流指正。


Lunker
7 声望0 粉丝