字母异位词:两个字符串s,t。倘若s t每个字符出现的次数一样,即为字母异位词
经典题目:242
-
可利用哈希表的存储方式,K-V,一个记录字符,一个记录次数
-
数组,又称小哈希表,一些代餐。如果只有字母,完全可以就定义一个长度为26的数组,然后位置即为对应的字母,对应的值可以是出现次数
-
该题解里有个很巧妙地比较出现次数的思路。刚开始的暴力想法:两个哈希表分别记录,然后再对比,光是想就操作麻烦。题解中的思路
-
for (int i = 0; i < s.length(); i++) { record[s.charAt(i) - 'a']++; } for (int i = 0; i < t.length(); i++) { record[t.charAt(i) - 'a']--; } for (int count: record) { if (count != 0) { return false; } } -
只用一个数组起到记录作用,一个字符串用来给它添加,一个字符串用来给它减小。如果符合情况,那么该数组的值都为0,否则要么多(正数)要么少(负数)
赎金信
题目:383
- 怎么说呢,感觉跟字母异位词是一个妈生的,换汤不换药
寻找两个数组的交集
题目:349
- 思路清楚,就是记录不同数组里出现的字符,因为此时它的字符范围不再拘泥于字母,所以还是用哈希表进行记录吧
- Set确保去重复内容,而且该题用不着K-V结构,知道Key即可。两次对比,寻找重复字符
- 主要是最后它这个获得答案用到的一堆方法,好骚哦
return resSet.stream().mapToInt(x -> x).toArray();//resSet为找到的重复字符,但是是Set形式,得把它转为数组. resSet.stream() :根据Set集合获取流 ......算了,我就当它是一种固定的把集合转为数组的模版吧。记不住也没关系,大不了直接创一个动态数组,找到一个重复的,add上去就行了
?数之和
两数之和
题目:1
- 需要知道组成target的两数及其位置,好消息是题目说了,有唯一的答案
- 那么既想知道是否有某一数出现,还想知道其位置,该用什么数据结构呢,对啦,哈希表。K-V分别对应数值和其位置
- 用num和target-num确认是否有符合条件的两数,不过注意,两数不能在一个位置。所以题解里现在把其放在一个for循环里吧,不过两个for循环也行,就是注意加上判定是否是一个位置的条件,当然,这样好像会慢一些。
三数之和
题目:15
- 它被放在哈希表里的原因大概就是一种爱屋及乌吧,以及告诉人们,不要看见类似的就觉得是一种解法
- 两数之和是利用哈希表,但是我三数之和and下面的四数之和其实是用双指针哒
- 那么为什么要用双指针+排序呢,小编也很好奇
- 虽然用哈希没有之前的两数之和方便,但是某种思路也是差不多的,就是以target和第一个选中的数为定点,然后去寻找其他的数。
- 那么为了方便找到正确的数,这边建议先给数组排序。一是可以根据排序后的数组,从第一个开始进行快速筛查,例如:从小到大,如果nums[0]已经大于target了,那么可以直接略过,收手吧,后边都是比target大的,怎么加都不是正确答案。二是方便去重,进行排序后,相同的数会堆在一起,想要去重直接下一个就行。三是方便利用双指针找一个确定的值,如果nums[left] + nums[right]偏大了,就让right--,让nums[right]变小。
- 因为是三个数,所以第一重for循环来确定一个定点nums[i],第二层for循环来找两个值使其等于target-nums[i](这里就是用到双指针)
- 细节问题便是去重方面。直接看代码随想录里它写的吧,懒得打字了x
四数之和
题目:18
- 是的,大致思路与三数之和一样,只是多了一层for循环
四数相加II
题目:454
- 你以为是用双指针,其实又是哈希表哒呦
- 前面的三数之和,四数之和为什么用双指针,因为它们都是在一个数组里的,用哈希表的话,查重去重剪枝就会很麻烦。但是注意看,这道题目里是四个独立的数组,不用想什么会有重复元素出现啥的
- 思路的话,两两分组,乍一看跟字母异位词那个思路类似。前两个数组用于往map里添加所有的可能和:temp = nums1[i] + nums2[j] 后两个数组用于对和做减法(target - temp),如果成功得到了对应的值,那么就获得一组数据。map里的K-V K:temp V:temp这个值出现的次数(毕竟不同的元素组合也会出现同一个值)
快乐数
题目:202
「快乐数」 定义为:
- 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。
- 然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。
- 如果这个过程 结果为 1,那么这个数就是快乐数
- 首先吐槽一句,这个快乐数可能不太让人感到快乐
- 无限循环 -> 会出现重复的数 -> 检查是否会有重复数出现 -> 所以会用到哈希法 fine
- 反正退出循环的条件不仅有 检查该值是否为1(是快乐数) 还有检测该值是否已经在HashSet里出现(出现了循环,不是快乐数,遗憾退场.jpg)
- 当然,还有一点很麻烦的(个人觉得)是分位......这里直接把题解中的分位然后相乘相加的代码记下来
while (n > 0) {
int temp = n % 10;//取最后一位
res += temp * temp;
n = n / 10;//舍弃已经被取的最后一位
}
一些不严谨总结
- 感觉这种会用到找重复东西的,都会沾点哈希表的边,还有会用到K-V结构的东西,感觉也沾边
- 限定为都是小写字母的,可以用青春版哈希表,即26位数组表示。甚至都还有K-V
- 只关心重没重复的,可以直接用Set
- 不止有小写字母,数据类型/范围更大的时候,就可以考虑用map
- 不过哈希对于去重剪枝好像有点不好搞(或许也是因为在一个数组里?)警惕什么三数之和陷阱,这种在一个数组里的,可能双指针会比较合适。而另一个四数相加,它们是有四个独立数组,用哈希表比指针方便多了。