day06:哈希表-242.有效的字母异位词、349.两个数组的交集、202.快乐数、1.两数之和
LeetCode 242.有效的字母异位词
题目链接:
文章讲解:
https://programmercarl.com/0242.%E6%9C%89%E6%95%88%E7%9A%84%E5%AD%97%E6%AF%8D%E5%BC%82%E4%BD%8D%E8%AF%8D.html
视频讲解:
https://www.bilibili.com/video/BV1YG411p7BA/
思路和解法:
哈希表:
题目中的字母异位词可以理解为:
两个字符串s和t,如果组成s和t的字母相同,且出现的次数相同,顺序可以不同,那么s和t就是字母异位词。如"abbccc"和"cccbba",两个字符串都由abc组成,虽然组成顺序不同,但是出现的次数一样,那"abbccc"和"cccbbaa"为字母异位词。
题目中说明字符串仅包含小写字母,所以可以考虑数组(数组也是哈希表的一种),数组大小为26,初始化为0。
因为字符a到字符z的ASCII是26个连续的数值,所以字符a映射为下标0,相应的字符z映射为下标25。
所以在遍历的时候,只要将s[i] - 'a’所在的元素做+1操作,t[i] - 'a’所在的元素做-1操作即可。遍历结束后,如果数组里有的数不为0,则说明字符串s和t一定是谁多了或少了,return false,反之return true。
public class Solution {
public bool IsAnagram(string s, string t) {
int sl = s.Length, tl = t.Length;
if(sl != tl)
return false;
int[] a = new int[26];
for(int i = 0; i < sl; i++)
{
a[s[i] - 'a']++;
a[t[i] - 'a']--;
}
foreach(var i in a)
{
if(i != 0)
return false;
}
return true;
}
}
LeetCode 349.两个数组的交集
题目链接:
文章讲解:
https://programmercarl.com/0349.%E4%B8%A4%E4%B8%AA%E6%95%B0%E7%BB%84%E7%9A%84%E4%BA%A4%E9%9B%86.html
视频讲解:
https://www.bilibili.com/video/BV1ba411S7wu/
思路和解法:
哈希表
采用HashSet解决(虽然题目中限制了两个数组的长度,但是这种类型的题更倾向于用HashSet)
1、将nums1的数值放进哈希表中。
2、再遍历nums2,遍历时,nums2中的每一个元素再去哈希表中去检查是否出现过,出现过,则放进result集合里。
public class Solution {
public int[] Intersection(int[] nums1, int[] nums2) {
if(nums1 == null || nums1.Length == 0 || nums2 == null || nums2.Length == 0)
return new int[0];
HashSet<int> set1 = new HashSet<int>(nums1);
HashSet<int> set2 = new HashSet<int>(nums2);
List<int> result = new List<int>();
foreach(var num in set1)
{
if(set2.Contains(num))
{
result.Add(num);
}
}
return result.ToArray();
}
}
LeetCode 202.快乐数
题目链接:
文章讲解:
https://programmercarl.com/0202.%E5%BF%AB%E4%B9%90%E6%95%B0.html
思路和解法:
哈希表:
题目中提到了可能会无限循环,换而言之,我们为了要避免这种情况,需要把每次的sum存到一个集合里,并判断集合中是否已经存在这个sum,这种快速判断一个元素是否出现在即合理的时候就要考虑哈希表了。
通过对n取余的操作获取到每个位的数并平方求和,然后存储到sum中。
循环结束条件是 n != 1且哈希表中不包含这个sum
public class Solution {
private int GetSum(int n)
{
int sum = 0;
while(n > 0)
{
sum += (n % 10) * (n % 10);
n /= 10;
}
return sum;
}
public bool IsHappy(int n) {
HashSet<int> result = new HashSet<int>();
while(n != 1 && !result.Contains(n))
{
result.Add(n);
n = GetSum(n);
}
return n == 1;
}
}
LeetCode 1.两数之和
题目链接:
文章讲解:
https://programmercarl.com/0001.%E4%B8%A4%E6%95%B0%E4%B9%8B%E5%92%8C.html
视频讲解:
https://www.bilibili.com/video/BV1aT41177mK/
思路和解法:
哈希表:
需要一个集合来存放我们遍历过的元素,然后在遍历数组的时候去询问这个集合,某元素是否遍历过,也就是是否出现在这个集合。
public class Solution {
public int[] TwoSum(int[] nums, int target) {
Dictionary<int, int> dict = new Dictionary<int, int>();
for(int i = 0; i < nums.Length; i++)
{
if(!dict.ContainsKey(nums[i]))
{
dict.Add(nums[i], i);
}
int tmp = target - nums[i];
if(dict.ContainsKey(tmp) && dict[tmp] != i)
{
return new int[]{i,dict[tmp]};
}
}
return new int[]{0,0};
}
}
总结:
遇到哈希表的时,数组、HashSet、HashMap分别在什么时候用
数组:数值比较小,且比较集中(如只有0、5、100000这三个数时,就要开100000长度的数组,空间浪费)
HashSet:没有数值限制,可能有上亿个时
HashMap:在需要用到键值对时采用。即Key-value的存储结构。