哈希表 Part1
242:有效的字母异位词
C++
在C语言中初始化数组全为零:
int a[10]={0};
char str[10]=“\0”; //等价于char str[10]={0}
本题思路
判断字母出现次数大部分情况下都是hash
和判断无非也就set,map,数组,由于本题只有26个字母,故用数组。
初始化数组的值为0,我们只要让出现的字母在相应的位置上加1,t数组在相应的位置上减一即可。
随后再遍历数组是否全为零即可
java
在这里插入代码片
```class Solution {
public boolean isAnagram(String s, String t) {
int arr[]=new int[26];
Arrays.fill(arr,0);
if(s.length()!=t.length())return false;
for(int i=0;i<s.length();i++){
arr[s.charAt(i)-'a']++;
arr[t.charAt(i)-'a']--;
}
for(int i=0;i<26;i++){
if(arr[i]!=0)return false;
}
return true;
}
}
在java中想用ascll要用charAt。java代码创建数组默认值为0
349. 两个数组的交集
看题解之前的问题:
隐隐约约知道要用数组,但是具体的方法就想不起来了
C++
set
由于是要不重复的数组返回值,故想到了set。
class Solution {
public:
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
unordered_set<int>result;
unordered_set<int>nums_set(nums1.begin(),nums1.end());
for (int num : nums2)
{
if(nums_set.find(num)!=nums_set.end())//find(key); //查找key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回set.end();
result.insert(num);
}
return vector<int>(result.begin(), result.end());
}
};
整体思路:
先把其中一个数组放入set中,这样可以打到去重的目的,再用另外一个数组在这个新的set数组中进行比较。如果找到有相同的,将相同的插入另外一个set数组,并返回这个数组。
要点在set的数组特性。
数组
由于力扣的条件改成了最大才1000,故我们可以用数组来解决本题;
方法和上一题类似。就是先定义一个数组,让nums1中的元素在对应的位置加一。让nums2中的元素检查是否能和加一的元素对上,如果可以,那说明这就是重叠的元素。将其插入set中。
class Solution {
public:
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
unordered_set<int> result_set; // 存放结果,之所以用set是为了给结果集去重
int hash[1005] = {0}; // 默认数值为0
for(int i=0;i<nums1.size();i++)
{
hash[nums1[i]]=1;
}
for(int i=0;i<nums2.size();i++)
{
if(hash[nums2[i]]==1)result_set.insert(nums2[i]);
}
return vector<int>(result_set.begin(), result_set.end());
}
};
java(待补全)
set
202. 快乐数
没有思路且感觉很难
解题方法
题目中有一个很重要的信息:无限循环,在这里我们就要想到用哈希算法了。
通过判断是否出现过数据来返回false。
还有一个很重要的就是计算sum的值。这里的算法应该多多学习。
class Solution {
public:
// 取数值各个位上的单数之和
int getSum(int n) {
int sum = 0;
while (n) {
sum += (n % 10) * (n % 10);
n /= 10;
}
return sum;
}
bool isHappy(int n) {
unordered_set<int> set;
while(1) {
int sum = getSum(n);
if (sum == 1) {
return true;
}
// 如果这个sum曾经出现过,说明已经陷入了无限循环了,立刻return false
if (set.find(sum) != set.end()) {
return false;
} else {
set.insert(sum);
}
n = sum;
}
}
};
java
public class istrue {
private static int getNext(int n) {
int totalSum = 0;
while (n > 0) {
int d = n % 10;
n = n / 10;
totalSum += d * d;
}
return totalSum;
}
public static boolean main(int n) {
HashSet<Integer> set = new HashSet<>();
while(true) {
int sum = getNext(n);
if (set.contains(sum))
return false;
if (sum == 1)
return true;
set.add(sum);
n = sum; // Update n for the next iteration
}
}
public static void main(String[] args) {
int n = 2; // Change this to the number you want to test
System.out.println(main(n));
}
}
这段代码是在idea里面写的。之前一直不太会在idea中写题目,也算是熟悉一下。
1. 两数之和
在做这一题时依然面临了困境,就是没思路,但我认为这种情况是因为基础知识,C++,java这些的一些特性没有掌握全面。但这没关系继续做。
- 本题使用map。因为要记录数组的值和下标。并在后续遍历中与已经遍历过的数进行比较。
- 使用map正好可以记录下key和value。
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
std::unordered_map <int,int> map;
for(int i = 0; i < nums.size(); i++) {
// 遍历当前元素,并在map中寻找是否有匹配的key
auto iter = map.find(target - nums[i]);
if(iter != map.end()) {
return {iter->second, i};
}
// 如果没找到匹配对,就把访问过的元素和下标加入到map中
map.insert(pair<int, int>(nums[i], i));
}
return {};
}
};