哈希表
哈希表使用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实现
定义一个HashMap
,key
来存放数值,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;
}
}