2021-04-06 LeetCode--哈希表

哈希表

哈希表使用O(N)的空间复杂度存储数据,并且以O(1)时间复杂度求解问题。
Java中的HashSet用于存储一个集合,可以查找元素是否在集合中。
Java中的HashMap主要用于映射关系,从而把两个元素联系起来。

1.两数之和

题目大意

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
在这里插入图片描述

解题思路

利用一个哈希表,key用于存放值,value用于存放对应的索引,遍历整个数组的时候将对应的键值对存放进入map中,如果map中存在target减去当前元素的值,就表示数组中存在着两个值的和等于target,那么就返回他们的索引。

代码实现

class Solution {
    public int[] twoSum(int[] nums, int target) {
        //哈希表 键存放值,值存放对应的索引
        Map<Integer,Integer> map=new HashMap<>();
        for(int i=0;i<nums.length;i++){
            if(map.containsKey(target-nums[i])){
                return new int[]{map.get(target-nums[i]),i};
            }else{
                map.put(nums[i],i);
            }
        }
        return null;

    }
}

217.存在重复元素

题目大意

给定一个整数数组,判断是否存在重复元素。
如果存在一值在数组中出现至少两次,函数返回true 。如果数组中每个元素都不相同,则返回 false
在这里插入图片描述

解题思路

利用一个HashSet来实现,如果某个元素在HashSet中存在,那就不会再加入,HashSet中存放无序不重复的元素。

代码实现

class Solution {
    public boolean containsDuplicate(int[] nums) {
        Set<Integer> set=new HashSet<>();
        for(int i=0;i<nums.length;i++){
            if(set.contains(nums[i])){
                return true;
            }
            set.add(nums[i]);
        }
        return false;
    }
}

优化版:

class Solution {
    public boolean containsDuplicate(int[] nums) {
        Set<Integer> set=new HashSet<>();
        for(int i=0;i<nums.length;i++){
            set.add(nums[i]);
        }
        return set.size()<nums.length;
    }
}

594.最长和谐子序列

题目大意

和谐数组是指一个数组里元素的最大值和最小值之间的差别 正好是 1 。
现在,给你一个整数数组 nums ,请你在所有可能的子序列中找到最长的和谐子序列的长度。
数组的子序列是一个由数组派生出来的序列,它可以通过删除一些元素或不删除元素、且不改变其余元素的顺序而得到。

解题思路

利用一个HashMap来记录每个元素以及出现的次数。统计每个元素以及比它大1的元素(需判断存不存在)的个数,返回其中的最大值即为最长的和谐子序列。

代码实现

class Solution {
    public int findLHS(int[] nums) {
        Map<Integer,Integer> map=new HashMap<>();
        //map中存放的是数组中的元素以及出现的次数
        for(int num:nums){
            map.put(num,map.getOrDefault(num,0)+1);
        }
        int longest=0;
        for(int num:map.keySet()){
            if(map.containsKey(num+1)){
                longest=Math.max(longest,map.get(num+1)+map.get(num));
            }
        }
        return longest;
    }
}

128. 最长连续序列

题目大意

给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。
在这里插入图片描述
要求以O(N)的时间复杂度求解。

解题思路

(一)HashMap实现
定义一个HashMapkey来存放数值,value存放以key开始的最长子序列的长度,利用递归来找连续序列,这里存在一个优化操作,就是每当不是第一次找以某值为开始的子序列时,如果之前已经通过递归找过了,那么就不载递归计算了,直接返回其值即可,最后找出一个最大值即可。
(二)HashSet实现
创建一个HashSet来存储数组中的所有值,然后开始找后续元素。需要注意的一点是:如果前一个当前元素的前一个元素在set中存在,那么就直接跳过,因为结果肯定不会优于已经加上前一个元素的结果。

代码实现

(一)HashMap实现

class Solution {
    public int longestConsecutive(int[] nums) {
        Map<Integer,Integer> map=new HashMap<>();
        for(int num:nums){
            map.put(num,1);
        } 
        for(int num:nums){
            forward(map,num);
        }
        return maxCount(map);
    }
    //递归实现找连续序列,这是map中的key为数值,value为以key开始的最长子序列
    public int forward(Map<Integer,Integer> map,int num){
        if(!map.containsKey(num)){
            return 0;
        }
        int cnt=map.get(num);
        //已经找过的就不在找了
        if(cnt>1){
            return cnt;
        }
        cnt=forward(map,num+1)+1;
        map.put(num,cnt);
        return cnt;
    }
    public int maxCount(Map<Integer,Integer> map){
        int max=0;
        for(int num:map.keySet()){
            max=Math.max(max,map.get(num));
        }
        return max;
    }
}

(二)HashSet实现

class Solution {
    public int longestConsecutive(int[] nums) {
       Set<Integer> set=new HashSet<>();
       for(int num:nums){
           set.add(num);
       }
       int longest=0;
       for(int num:nums){
           if(!set.contains(num-1)){
               int currentNum=num;
               int currentStreak=1;
               while(set.contains(currentNum+1)){
                   currentNum++;
                   currentStreak++;
               }
               longest=Math.max(currentStreak,longest);
           }
       }
       return longest;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值