最长和谐子序列-LeetCode

题目

和谐数组是指一个数组里元素的最大值和最小值之间的差别 正好是 1 。现在,给你一个整数数组 nums ,请你在所有可能的子序列中找到最长的和谐子序列的长度。
数组的子序列是一个由数组派生出来的序列,它可以通过删除一些元素或不删除元素、且不改变其余元素的顺序而得到。
示例 1:
输入:nums = [1,3,2,2,5,2,3,7] 输出:5 解释:最长的和谐子序列是 [3,2,2,2,3]
示例 2:
输入:nums = [1,2,3,4] 输出:2
示例 3:
输入:nums = [1,1,1,1] 输出:0
题目来源:力扣(LeetCode)594
链接:https://leetcode-cn.com/problems/longest-harmonious-subsequence

官方解法

方法一:枚举

我们可以枚举数组中的每一个元素,对于当前枚举的元素 x,它可以和 x + 1 组成和谐子序列。我们再遍历一遍整个数组,找出等于 x 或 x + 1 的元素个数,就可以得到以 x 为最小值的和谐子序列的长度。
复杂度分析:
时间复杂度:O(N^2),其中 N 是数组的长度。
空间复杂度:O(1)。

方法二:哈希映射

在方法一中,我们枚举了 x 后,遍历数组找出所有的 x 和 x + 1。我们也可以用一个哈希映射(HashMap)来存储每个数出现的次数,这样就能在 O(1)O(1) 的时间内得到 x 和 x + 1 出现的次数。
我们首先遍历一遍数组,得到哈希映射。随后遍历哈希映射,设当前遍历到的键值对为 (x, value),那么我们就查询 x + 1 在哈希映射中对应的值,就得到了 x 和 x + 1 出现的次数。
复杂度分析:
时间复杂度:O(N),其中 N 是数组的长度。
空间复杂度:O(N),用来存储哈希映射。

方法三:哈希映射 + 单次扫描

在方法二中,我们需要对数组进行一次扫描,再对哈希映射进行一次扫描。事实上,我们也可以设计出只进行一次扫描的算法。
我们扫描一次数组,当扫描到元素 x 时,我们首先将 x 加入哈希映射,随后获取哈希映射中 x - 1, x, x + 1 三者出现的次数 u, v, w,那么 u + v 即为 x - 1, x 组成的和谐子序列的长度,v + w 即为 x, x + 1 组成的和谐子序列的长度。假设数组中最长的和谐子序列的最后一个元素在数组中的位置为 i,那么在扫描到 nums[i] 时,u + v 和 v + w 中一定有一个就是答案。因此这种方法可以找到最长的和谐子序列的长度。

哈希映射

详细解释(英文版本):
https://docs.oracle.com/javase/7/docs/api/java/util/HashMap.html

创建HashMap变量
创建HashMap变量需指定键和值的数据类型,格式如下。
HashMap<Integer, String> map = new HashMap<>();

HashMap的put方法——添加值
通过HashMap的put方法可以向变量中添加值。put方法有两个参数,就是要添加的数据的键和值。
map.put(num, map.getOrDefault(num, 0) + 1);

HashMap的get方法——取值
通过HashMap的get方法可以向变量中取值。get方法需要传入一个参数,那个参数是键值,在HashMap中,键值是唯一的。
res = Math.max(res, map.get(key) + map.get(key + 1));

HashMap的keySet()方法——遍历HashMap变量
遍历HashMap变量不能像遍历数组那样直接通过索引值来遍历,可以通过HashMap的keySet()方法获取变量中存放的所有键值,然后再通过遍历键获取对应的值

修改——将原有的值覆盖
在HashMap中,想修改其中存放的值,可以通过使用put方法,将原有的值覆盖。

HashMap的remove方法——删除HashMap变量
由于键值是对应的,所以只有删除HashMap中的键,就会连同删除键对应的值。通过使用HashMap的remove方法,可以删除HashMap变量中的内容。这里讲一下remove方法的两个重载函数,remove(Object key) 和 remove(Object key, Object value)。 这两个函数的区别在于,remove(Object key)直接删除对应的键,而remove(Object key, Object value)需要键和值都对应时才会删除HashMap变量中的内容。

    public static  void HashMap(){
        //创建hashmap变量
        HashMap<Integer, String> map = new HashMap<>();
        String[] names={"老大","老二","老三","老四"};
        for (int i=0;i< names.length;i++){
            //向hashmap变量添加值
            map.put((i+1),names[i]);
        }
        System.out.println(map);

        //从HashMap变量获取值
        String namehashmap=map.get(4);
        System.out.println("从HashMap变量获取值:"+namehashmap);

        //遍历HashMap变量
        /*  遍历HashMap变量不能像遍历数组那样直接通过索引值来遍历,
        可以通过HashMap的keySet()方法获取变量中存放的所有键值,然后再通过遍历键获取对应的值 */
        System.out.print("遍历HashMap变量:");
        for (Integer id:map.keySet()){
            System.out.print("  id="+id+"  name:"+map.get(id));
        }

        //修改HashMap变量
        //在HashMap中,想修改其中存放的值,可以通过使用put方法,将原有的值覆盖。
        System.out.println();
        System.out.print("修改HashMap变量:");
        System.out.print("修改前:"+map.get(4));//4-老四
        map.put(4,"老五");
        System.out.print("修改后:"+map.get(4));//4-老四


        //删除HashMap变量中的值
        /*
        由于键值是对应的,所以只有删除HashMap中的键,就会连同删除键对应的值。
        通过使用HashMap的remove方法,可以删除HashMap变量中的内容。
        这里讲一下remove方法的两个重载函数,
        remove(Object key) 和 remove(Object key, Object value)。
        这两个函数的区别在于,remove(Object key)直接删除对应的键,
        而remove(Object key, Object value)需要键和值都对应时才会删除HashMap变量中的内容。
         */
        System.out.println();
        System.out.println("删除HashMap变量:");
        System.out.println("删除前HashMap变量:");
        for (Integer id:map.keySet()){
            System.out.print("  id="+id+"  name:"+map.get(id));
        }
        map.remove(2);
        System.out.println();
        System.out.println("删除后HashMap变量:");
        for (Integer id:map.keySet()){
            System.out.print("  id="+id+"  name:"+map.get(id));
        }
    }

在这里插入图片描述

增强for循环

    public static void formedthod(){
        int[] arr= {1,2,3,4};
        System.out.println();
        for (int num:arr){
            System.out.print(num+" ");
        }
    }

结果
官方解释比较详细有PPT分析,建议如果没看懂移步官方题解,本文档仅供理解补充!
本博客是平时学习笔记没有很多技术含量,小白可以来学习一下,也欢迎各位大佬指点!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值