问题分析
我以为我的链表那一章还能有个第二节,做到后面发现跟我前面发的几个什么反转链表一样,就没有继续做了。就往下做了哈希表这部分,哈希表的话,做完之后我觉得跟前面的滑动窗口还有点关系,那里面存储也用的哈希表:key-value。
这里主要是涉及到242,383,49,438题,难点的题就是49,这个真是一个medium做一天。后面分析。
思路分析
遇到某个元素是否在数组中出现就用哈希法。我理解的是一个字符出现次数需要计数的时候,哈希法就用到了。
第一题第二题只要知道这个字符串转化为字符数组的方法就行,这两种转化都行。
242题:
class Solution {
public boolean isAnagram(String s, String t) {
int record[] = new int[26];
char str[] = s.toCharArray();//toCharArray()的一种字符串到字符数组额遍历
for(char i = 0;i < str.length; i++){
record[str[i] - 'a']++;
}
for(char i = 0;i < t.length(); i++){//charAt()第二种转换遍历
record[t.charAt(i) - 'a']--;
}
for(int i = 0;i < record.length; i++){
if(record[i] != 0)
return false;
}
return true;
}
}
383题:
class Solution {
public boolean canConstruct(String ransomNote, String magazine) {
int record[] = new int[26];
char mag[] = magazine.toCharArray();
for(int i = 0;i < mag.length; i++){
record[mag[i] - 'a']++;
}
for(int i = 0;i < ransomNote.length(); i++){
if(record[ransomNote.charAt(i) - 'a'] > 0)
record[ransomNote.charAt(i) - 'a']--;
else
return false;
}
return true;
}
}
第三题大家普遍用的排序,我也就用了。但最困难的是无法对应好map和list的关系,网上普遍第一种方法,我注释好了:
class Solution {
public List<List<String>> groupAnagrams(String[] strs) {//List<List<String>>二维String列表
Map<String, List<String>> map = new HashMap<>();//map中的key来存储排序后的新字符串
if(strs == null || strs.length == 0)//边界问题
return new ArrayList<>();
for(int i = 0;i < strs.length; i++){//排序
char c[] = strs[i].toCharArray();//字符串数组转换为字符数组
Arrays.sort(c);
String str2 = String.valueOf(c);//排序后再转化为字符串
//判断map中有没有这个字符串,如果没有这个字符串,
//说明还没有出现和这个字符串一样的字母异位词,
//要新建一个list,把它存放到map中
if(!map.containsKey(str2))
map.put(str2, new ArrayList<>());
map.get(str2).add(strs[i]);//把字符串存放到对应的list中
}
return new ArrayList<>(map.values());
}
}
前面还可以理解,走到最后总是无法对应,尤其是那么多new ArrayList()简直逼疯我这个菜鸡,我初始化了好几个list,怎么都不对,这时候就要注意题目会主动给出那个开头,在那个开头就表明了List<List</String/>>我不会用那个,,,转换,就这么看吧。反正也没人看。。。继续,这是个二维字符串list。还涉及到深拷贝,浅拷贝,大致略懂。然后找到了第二个方法,比较好懂:
class Solution {
public List<List<String>> groupAnagrams(String[] strs) {//List<List<String>>二维String列表
Map<String, Integer> map = new HashMap<>();
List<List<String>> list = new ArrayList<>();//用list来存异位比较后的字符串数组,作为最终返回值
int count = 0;
for (int i = 0; i < strs.length; i++) {
char c[] = strs[i].toCharArray();//字符串数组转换为字符数组
Arrays.sort(c);//排序
String str2 = String.valueOf(c);
if (!map.containsKey(str2)) {
list.add(new ArrayList<>());//其实就是扩充list,存在没有的新值我就建一个
map.put(str2, count);//跟map说把新值放进去,然后在下面几轮进行比较
count++;//计数,计算的是map的value,对应的是list的key
}
list.get(map.get(str2)).add(strs[i]);//得到map的value去作为list的key,
// 找到对应list对应的key之后,list的value为strs[i],value可不唯一
//但key唯一
}
return list;
}
}
第一个我到现在都是懵懵懂懂。我还是很理解第二个方法,简单一点。
438题就是滑动窗口双指针,没有啥技术含量,但我依然看了题解,哈哈哈哈。贴代码。
class Solution {
public List<Integer> findAnagrams(String s, String p) {//滑动窗口双指针问题
List<Integer> list = new ArrayList<>();
int m = s.length();
int n = p.length();
char str[] = p.toCharArray();
int pCount[] = new int[26];//存放p中的各个字符数量
int sCount[] = new int[26];
for(int i = 0; i < n; i++){//计算好p字符的情况
pCount[str[i] - 'a']++;
}
int left = 0;
int right = 0;
char str2[] = s.toCharArray();//将字符串转化为字符数组
for(right = 0; right < m; right++){
sCount[str2[right] - 'a']++;
while(sCount[str2[right] - 'a'] > pCount[str2[right] - 'a']){
sCount[str2[left] - 'a']--;//对while进行注释,一旦s某个字符数量大于p某个字符数量,
//说明窗口大了,要缩小
left++;
}
if(right - left + 1 == n)
list.add(left);
}
return list;
}
}
到此结束,这是昨晚上剩下的事了,今天上午的任务是继续修改我的论文,555,写加改都一年了,加油,导师说下周投。。。