242.有效的字母异位词 349. 两个数组的交集 202. 快乐数 1. 两数之和
242.有效的字母异位词
1.思路
数组其实就是一个简单哈希表,而且这道题目中字符串只有小写字符,那么就可以定义一个数组,来记录字符串s里字符出现的次数。
- 定一个数组叫做record,大小为26 就可以了,初始化为0,因为字符a到字符z的ASCII也是26个连续的数值。record用来上记录字符串s里字符出现的次数。
- 需要把字符映射到数组也就是哈希表的索引下标上,因为字符a到字符z的ASCII是26个连续的数值,所以字符a映射为下标0,相应的字符z映射为下标25。
再遍历 字符串s的时候,只需要将 s[i] - ‘a’ 所在的元素做+1 操作即可,并不需要记住字符a的ASCII,只要求出一个相对数值就可以了。 这样就将字符串s中字符出现的次数,统计出来了。
那看一下如何检查字符串t中是否出现了这些字符,同样在遍历字符串t的时候,对t中出现的字符映射哈希表索引上的数值再做-1的操作。- 那么最后检查一下,record数组如果有的元素不为零0,说明字符串s和t一定是谁多了字符或者谁少了字符,return false。
最后如果record数组所有元素都为零0,说明字符串s和t是字母异位词,return true。
时间复杂度为O(n),空间上因为定义是的一个常量大小的辅助数组,所以空间复杂度为O(1)
2.代码实现
class Solution {
public boolean isAnagram(String s, String t) {
int[] record= new int[26];
for(int i=0; i<s.length();i++)
record[s.charAt(i)-'a']++;//统计s里出现过的字母次数并放入record
for(int i=0; i<t.length();i++)
record[t.charAt(i)-'a']--;//减去t里出现过的字母的次数
for(int count: record){
if(count!=0)
return false;
}
return true;
}
}
349. 两个数组的交集
1.思路
结构体选择思路:
使用数组来做哈希的题目,是因为题目都限制了数值的大小。而且如果哈希值比较少、特别分散、跨度非常大,使用数组就造成空间的极大浪费。
此时就要使用另一种结构体了,set ,关于set,C++ 给提供了如下三种可用的数据结构:
std::set
std::multiset
std::unordered_set
std::set和std::multiset底层实现都是红黑树,std::unordered_set的底层实现是哈希表, 使用unordered_set 读写效率是最高的,并不需要对数据进行排序,而且还不要让数据重复,所以选择unordered_set。
思路如图:
后来本题限制了数组大小为1000,因此可以用数组做了。
能用数组做优先用数组做,直接使用set 不仅占用空间比数组大,而且速度要比数组慢,set把数值映射到key上都要做hash计算的。
2.代码实现
import java.util.HashSet;
import java.util.Set;
class Solution {
public int[] intersection(int[] nums1, int[] nums2) {
if(nums1==null||nums2==null||nums1.length==0||nums2.length==0){
return new int[0];
}
Set<Integer> set1 = new HashSet<>();//转化数组nums1为set
//Set<Integer> set1 = new HashSet<>();
Set<Integer> resSet=new HashSet<>();//存放结果
for(int i: nums1)
set1.add(i);
for(int i: nums2){
if(set1.contains(i))
resSet.add(i);
}
//方法1:将结果集合转为数组
return resSet.stream().mapToInt(x -> x).toArray();
//方法2:另外申请一个数组存放setRes中的元素,最后返回数组
int[] arr=new int[resSet.size()];
int j=0;
for(int i: resSet)
arr[j++]=i;
return arr;
}
}
202. 快乐数
1.思路
这道题目使用哈希法,来判断这个sum是否重复出现,如果重复了就是return false, 否则一直找到sum为1为止。
判断sum是否重复出现就可以使用unordered_set。
2.代码实现
class Solution {
public boolean isHappy(int n) {
Set<Integer> record=new HashSet<>();//存放sum
while(1!=0){
n=getNextnumber(n);//得出sum
if(n==1)
return true;
else if(record.contains(n)){
return false;
}
else
record.add(n);
}
}
//计算每个位平方和
private int getNextnumber(int n){
int res=0;
while(n>0){
int temp=n%10;
res+=temp*temp;
n/=10;
}
return res;
}
}
1. 两数之和
1.思路
四问:
1.为什么使用哈希法
当我们需要查询一个元素是否出现过,或者一个元素是否在集合里的时候,就要第一时间想到哈希法。本题呢,我就需要一个集合来存放我们遍历过的元素,然后在遍历数组的时候去询问这个集合,某元素是否遍历过,也就是 是否出现在这个集合。
2.为什么使用map,有什么作用
因为本地,我们不仅要知道元素有没有遍历过,还有知道这个元素对应的下标,需要使用 key value结构来存放,key来存元素,value来存下标,那么使用map正合适。
3.如果使用c++,为什么使用unordered_map
数组的大小是受限制的,而且如果元素很少,而哈希值太大会造成内存空间的浪费。
set是一个集合,里面放的元素只能是一个key,而两数之和这道题目,不仅要判断y是否存在而且还要记录y的下标位置,因为要返回x 和 y的下标。所以set 也不能用。
此时就要选择另一种数据结构:map ,map是一种key value的存储结构,可以用key保存数值,用value在保存数值所在的下标。
过程如下:
The twoSum method provided in the Solution class is designed to find two numbers in the given nums array that add up to the specified target. The method returns an array of two integers representing the indices of the two numbers that sum up to the target value. Here’s a step-by-step explanation of the algorithm implemented in the method:
An array res of size 2 is initialized to store the indices of the two numbers that add up to the target.
A HashMap named map is created to store numbers and their corresponding indices from the nums array. The key is the number, and the value is the index of that number.
The method iterates over the nums array using a for loop.
Inside the loop, for each number nums[i], the method calculates temp, which is the difference between the target and the current number (target - nums[i]). This temp represents the number that, when added to nums[i], equals the target.
The method then checks if temp is already a key in the map. If it is, it means that a pair of numbers has been found where nums[i] + temp = target.
When a pair is found:
The index of temp is retrieved from the map and stored in res[0].
The current index i is stored in res[1].
The loop is immediately terminated with a break statement since the solution has been found.
If temp is not in the map, the current number nums[i] and its index i are put into the map. This is done so that if the complement of nums[i] (which is target - nums[i]) is encountered later in the array, the current index can be retrieved.
After the loop completes (either by finding a solution or by reaching the end of the array), the res array is returned. If a pair that adds up to the target was found, res will contain their indices. If no such pair exists, res will contain the default values (0, 0), assuming the input guarantees at least one solution as per the problem statement typically associated with the two-sum problem.
In summary, this twoSum method uses a single-pass HashMap approach, which provides a time-efficient way to find the two indices required for the solution. The time complexity of this method is O(n), as it traverses the list only once and the hash table (in this case, the HashMap) reduces the look-up time to O(1).
2.代码实现
class Solution {
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];//要寻找的值
if(map.containsKey(temp)){
res[1]=i;//存此时遍历到的下标
res[0]=map.get(temp);//存搜索到的值的下标
break;
}
map.put(nums[i],i);//未搜索到差值 就将此时遍历的值和下标插入map
}
return res;
}
}