提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
提示:今天开始我们学习哈希表:
提示:以下是本篇文章正文内容
一、242. 有效的字母异位词
-
题目描述
给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。
注意:若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词。
示例 1:
输入: s = “anagram”, t = “nagaram”
输出: true
示例 2:输入: s = “rat”, t = “car”
输出: false -
双循法:
String s, t为输入
①我们可以通过s.length();获取字符串长度
②因为我们需要输入的两个字符串可能包含相同的字母,因此我们每次查到一组匹配的都要删除查到的字母。
③但是因为字符串String不可修改,因此我们只能引入StringBuilder类进行删除操作
④利用String类的方法 if(s.charAt(i) == tMutable.charAt(j))进行匹配工作
⑤查到后我们利用StringBuilder类的方法,tMutable.deleteCharAt(j)进行删除工作;最终利用双循环完成任务。
class Solution {
public boolean isAnagram(String s, String t) {
if (s.length() != t.length()) {
return false;
}
StringBuilder tMutable = new StringBuilder(t); // 创建一个可变的字符串t,使得我们可以从中删除字符
for (int i = 0; i < s.length(); i++) {
boolean found = false;
for (int j = 0; j < tMutable.length(); j++) {
if (s.charAt(i) == tMutable.charAt(j)) {
tMutable.deleteCharAt(j); // 删除找到的字符
found = true;
break;
}
}
if (!found) {
return false;
}
}
return true;
}
}
- 哈希法
三种数据结构:数组,set,map
数组对应范围可控的情况,如hash[26]对应26个字母。
set:只需要跟踪一个集合的元素,并查询元素是否存在。
map:当需要存储"key"时,即当数据有关联信息时。
要点:
- 字符串获取对应位置字符的方法s.charAt(i);
- 26个字母ASCII码连续,可以取a-z对a的相对位置对应hash数组的0-25位。
class Solution {
public boolean isAnagram(String s, String t) {
if (s.length() != t.length()) {
return false;
}
int[] hash= new int [26];
for(int i=0; i<s.length(); i++){
// (s[i]-'a')取字母的ASCII码
hash[s.charAt(i)-'a']++;
}
for(int j = 0; j<t.length(); j++){
hash[t.charAt(j)-'a']--;
}
for(int i =0; i<26; i++){
if(hash[i]!=0)
return false;
}
return true;
}
}
二、349. 两个数组的交集
1. 思路:
查找数组的交集,我们利用unorder set这样的数据结构可以自动去重;
我们先用HashSet<> set1存储第一个数组中含有的元素;再遍历第二个数组的过程中,如果集合set1含有第二个数组中的元素,那么我们就把重复的元素放入第二个set resSet中,这也就是本体的结果。但是最终我们得到的是一个resSet是一个HashSet,我们需要把这样的HashSet转为数组
最后利用
for(int i : resSet){
arr[z++]=i;
}
得到结果数组。
``
2.代码
import java.util.HashSet;
import java.util.Set;
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> set1 = new HashSet<>();
Set<Integer> resSet = new HashSet<>();
for(int i:nums1){
set1.add(i);
}
for(int j: nums2 ){
if(set1.contains(j)){
resSet.add(j);
}
}
int[] arr= new int[resSet.size()];
int z =0;
for(int i : resSet ){
arr[z++]=i;
}
return arr;
}
}
三、202. 快乐数
1. 题目描述:
编写一个算法来判断一个数 n 是不是快乐数。
「快乐数」 定义为:
对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。
然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。
如果这个过程 结果为 1,那么这个数就是快乐数。
如果 n 是 快乐数 就返回 true ;不是,则返回 false 。
2. 思路:
本题分为两步
- 获取这个数各位平方合
private int getNextNumbers(int n){
int sum =0;
int tmp; //tmp是末位,这个function是逐一移项取末位平方和,计算各位平方和的方式计算
while(n>0){
tmp=n%10;
sum+=tmp*tmp;
n/=10 ; //整数除法,不保留小数,相当于移位
}
return sum;
}
- 当各项平方和为1时,返回true结束循环;此外,各项平方和遇到出现过的平方和时代表进入循环,直接return false;
因此采用如下语句
Set<Integer> set1 = new HashSet<Integer>();
while(n!=1){
if(set1.contains(n)){
return false;
}
set1.add(n);
n=getNextNumber(n);
}
四、1. 两数之和
public int[] twoSum(int[] nums, int target) {
int[] res = new int[2];
if(nums == null || nums.length == 0){
return res;
}
Map<Integer, Integer> map = new HashMap<>();
for(int i = 0; i < nums.length; i++){
int temp = target - nums[i]; // 遍历当前元素,并在map中寻找是否有匹配的key
if(map.containsKey(temp)){
res[1] = i;
res[0] = map.get(temp);
break;
}
map.put(nums[i], i); // 如果没找到匹配对,就把访问过的元素和下标加入到map中
}
return res;
}