java实现hash表基本操作
HashMap散列表基本操作
//创建hash
//(创建时key-value的数据类型可不同)
HashMap<instanceof(key), instanceof(value)> hashmap = new HashMap<instanceof(key), instanceof(value)>();
/*创建Hashmap<Integer, String> hashmap = new Hashmap<int,String>();为例子按索引增删改查*/
//增
hashmap.put(1, "str1");
hashmap.put(2, "str2");
/*执行后表内为{1="str1", 2="str2"}*/
//删
hashmap.remove(2);//删某key对应value
/*执行后表内为{1="str1"}*/
hashmap.clear();//清空所有键值对
//改(替换指定key的value)
hashmap.replace(1, "string1");
/*返回0*/
//查
hashmap.isEmpty();//判空
hashmap.get(1);
hashmap.size();
/*返回表中键值对个数1*/
hashmap.getOrDefault(key, defaultValue);
/*表中有值返回值,没有值则使用默认值defaultValue*/
hashmap.values();
/*返回{"string1"},所有key对应的value组成表*/
//forech遍历表中每一个键值对组成的对象entry
for(var entry : hashmap.entrySet())
{
int key = entry.getKey();
int val = entry.getValue();
}
HashSet集合基本操作
//创建hashset
Set<Integer> hashset= new HashSet<Integer>();
//增
hashset.add(1);
//查
hashset.contains(1);
//删
hashset.remove(1);
hashset.clear();//删除所有元素
数组实现hash表
- 题目链接:寻找两字符串相同异位字符
- 我的解法:
class Solution {
public boolean isAnagram(String s, String t) {
if(s.length() != t.length()) return false;
char cnt[] = new char[26];
for(int i = 0; i < s.length(); i++)
{
int idx = s.charAt(i) - 'a';
cnt[idx]++;
}
for(int i = 0; i < t.length(); i++)
{
int idx = t.charAt(i) - 'a';
cnt[idx]--;
if(cnt[idx] < 0) return false;
}
for(int i = 0; i < 26; i++)
{
if(cnt[i] > 0) return false;
}
return true;
}
}
java字符串不能像c++一样直接遍历,用toCharArray()后foreach和charAt(index)方可实现遍历。
- 复杂度:时间复杂度 O ( n ) O(n) O(n),空间复杂度 O ( 1 ) O(1) O(1)
HashSet实现哈希表
- 题目链接:两数组不重复的相同元素
- 我的解法:由于数组中正整数范围的限制,使用一个数组记录+hashset存储两数组相同元素的方法记录,本质还是使用数组实现的hash表
class Solution {
public int[] intersection(int[] nums1, int[] nums2) {
int[] cnt1 = new int[1001];
HashSet<Integer> ans = new HashSet<Integer>();
for(int i = 0; i < nums1.length; i++) cnt1[nums1[i]]++;//构建hash表
for(int i = 0; i < nums2.length; i++)
{
if(cnt1[nums2[i]] > 0) ans.add(nums2[i]);
}
int size = ans.size();
int answer[] = new int[size];
int idx = 0;
for(int num : ans) answer[idx++] = num;
return answer;
}
}
- 复杂度:时间复杂度 O ( n + m ) O(n + m) O(n+m),对应遍历原来两数组和将hashmap转换成数组形式输出的复杂度。
- 拓展解法:当数组中存储的数字对应的取值范围没有被给出时,使用set构建hash表可避免空间浪费
class Solution {
public int[] intersection(int[] nums1, int[] nums2) {
//判断是否需要寻找
if (nums1 == null || nums1.length == 0 || nums2 == null || nums2.length == 0) {
return new int[0];
}
Set<Integer> set = new HashSet<>();
Set<Integer> res = new HashSet<>();
//遍历数组1
for (int i : nums1) {
set.add(i);
}
//遍历数组2的过程中判断哈希表中是否存在该元素
for (int i : nums2) {
if (set.contains(i)) {
res.add(i);
}
}
//set转化为数组的另一种方法
return res.stream().mapToInt(x -> x).toArray();
}
}
- 题目链接:快乐数果然快乐
- 最终解法:用set充当hash表,这里审题(无限循环==重新计算出来的n会再次出现)
class Solution {
public boolean isHappy(int n) {
Set<Integer> hashset = new HashSet<Integer>();
while((n != 1) && (!hashset.contains(n)))
{
hashset.add(n);
n = cntHappyNum(n);
}
if(n == 1) return true;
return false;
}
public int cntHappyNum(int ans){
int sum = 0;
while(ans > 0)
{
sum += (ans % 10) * (ans % 10);
ans = ans / 10;
}
return sum;
}
}
- 复杂度:时间复杂度 O ( l o g n ) O(logn) O(logn),空间复杂度 O ( l o g n ) O(logn) O(logn),是cntHappyNum函数带来的复杂度
HashMap实现哈希表
- 题目链接:
- 我的解法:用哈希表同时记录数字和下标,单向遍历找当前num和为target的搭子有则返回,没则加入当前num进表
class Solution {
public int[] twoSum(int[] nums, int target) {
int ans[] = new int[2];
HashMap<Integer,Integer> hashmap = new HashMap<Integer, Integer>();
for(int i = 0; i < nums.length; i++)
{
int num = nums[i];
if(hashmap.containsKey(target - num))
{
ans[0] = hashmap.get(target-num);
ans[1] = i;
}
else hashmap.put(num, i);
}
return ans;
}
}
看题解还可以两个指针相向而行双管齐下,执行速度会快很多
- 复杂度:时间复杂度 O ( n ) O(n) O(n),空间复杂度 O ( n ) O(n) O(n)