哈希表理论基础
* 解决的问题为“快速判断一个元素是否出现在集合里”。O(1)就可以做到。
*HashSet:
* 基于哈希表实现的,主要用于存储不重复的元素。
* 允许储存null
* 内部使用HashMap来实现,实际上将对象作为HashMap的键,使用固定“present”对象 作为值。
* 插入、删除、查询复杂度为0(1).如果哈希冲突严重,效率降到0(n)
*HashMap:
*插入、删除、查询平均复杂度为0(1). 如果哈希冲突严重,效率降到0(n).
242.有效的字母异位词
* 自我尝试
* 代码
class Solution {
public boolean isAnagram(String s, String t) {
int[] arr = new int[26];
for (int i=0; i<s.length();i++){
arr[s.charAt(i)-'a']++;
}
for (int i=0; i<t.length();i++){
arr[t.charAt(i)-'a']--;
}
for(int ele:arr){
if(ele!=0){
return false;
}
}
return true;
}
}
* 收获
* 对于string的遍历要通过for loop使用charAt
* 自我尝试
* 代码
import java.util.HashSet;
class Solution {
public int[] intersection(int[] nums1, int[] nums2) {
HashSet<Integer> st1 = new HashSet<>();
HashSet<Integer> rslt = new HashSet<>();
for(Integer ele: nums1){
st1.add(ele);
}
for(Integer ele: nums2){
if(st1.contains(ele)){
rslt.add(ele);
}
}
return rslt.stream().mapToInt(i->i).toArray();
}
}
* 收获
* autoBoxing的for loop
for(int ele: nums1) { //这里int换成integer都是可以的
// ...
}
* HashSet的方法: contains() & add
* 将HashSet变为int array的办法:使用stream api即 stream().mapToInt(i->i).toArray();
* 确认set里元素的数量方法: set.size()
* 范例题解
* 代码 - 哈希数组法,因为限制了数字范围
class Solution {
public int[] intersection(int[] nums1, int[] nums2) {
int[] arr = new int[1001];
for(int ele: nums1){
if(arr[ele]==0){
arr[ele]++;
}
}
for(int ele:nums2){
if(arr[ele]==1){
arr[ele]++;
}
}
List<Integer> rslt = new ArrayList<>();
for(int i=0; i<arr.length;i++){
if(arr[i]==2){
rslt.add(i);
}
}
return rslt.stream().mapToInt(i->i).toArray();
}
}
* 收获
* stream()方法是collection接口里的一个方法。实现这个接口的,如ArrayList,LinkedList,HashSet等等都可以使用
* HashMap
自身不是一个Collection
,但它的values()
, keySet()
, 和 entrySet()
方法分别返回表示其值、键和键值对的集合视图,这些视图实现了Collection
接口或其子接口。
* 普通数组声明后是一个连续存储的区间,需要声明size。因此,引入ArrayList<>可以弹性扩大。
* 范例题解
* 代码
import java.util.HashSet;
class Solution {
public boolean isHappy(int n) {
//只要遇到重复的数字就说明不会到1了。涉及到重复,就用哈希法
HashSet<Integer> hs = new HashSet<>();
while(n!=1 && !hs.contains(n)){
hs.add(n);
n = getSquareSum(n);
}
return n==1;
}
private int getSquareSum(int n){
int result = 0;
while(n>0){
result+= (n % 10)*(n %10);
n = n /10;
}
return result;
}
}
* 收获
* 当我们遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法了
* 一个不断取余的操作,来获取square sum。
* 自我尝试
* 代码-暴力法
class Solution {
public int[] twoSum(int[] nums, int target) {
// 暴力法
int[] rslt = new int[2];
for(int i=0; i<nums.length;i++){
for(int j=i+1; j<nums.length;j++){
if(nums[i]+nums[j]==target){
rslt[0]=i;
rslt[1]=j;
break;
}
}
}
return rslt;
}
}
* 代码
import java.util.HashMap;
class Solution {
public int[] twoSum(int[] nums, int target) {
// HashMap法
int[] result = new int[2];
HashMap<Integer, Integer> hm = new HashMap<>();
// 1. 将所有元素先按照<值,下标> 装入map
for(int i=0; i<nums.length;i++){
hm.put(nums[i],i);
}
// 2. 遍历数组,以target-值的方式查找是否有对应key (注意不能重复使用同一个元素) 添加index到result里并返回。
for (int j =0;j<nums.length;j++){
int tmp = target-nums[j];
if(hm.containsKey(tmp) && hm.get(tmp)!=j ){
result[0]=hm.get(tmp);
result[1]=j;
}
}
return result;
}
}
* 范例题解
* 代码-hashMap法。
* 思路:通过一次loop迭代,在添加元素的同时,避免了重复的check匹配!很巧妙
import java.util.HashMap;
class Solution {
public int[] twoSum(int[] nums, int target) {
// HashMap法
int[] result = new int[2];
HashMap<Integer, Integer> hm = new HashMap<>();
for(int i=0; i<nums.length;i++){
int temp = target-nums[i];
if(hm.containsKey(temp)){
result[0]=i;
result[1]=hm.get(temp);
break;
}
hm.put(nums[i],i);
}
return result;
}
}
* 收获
* hashmap的方法: put(key,value) 添加元素; containsKey(key)检查key是否存在;
get(key) 获取value