49. 字母异位词分组
给定一个字符串数组,将字母异位词组合在一起。字母异位词指字母相同,但排列不同的字符串。
示例:
输入: [“eat”, “tea”, “tan”, “ate”, “nat”, “bat”]
输出:
[
[“ate”,“eat”,“tea”],
[“nat”,“tan”],
[“bat”]
]
说明:
所有输入均为小写字母。
不考虑答案输出的顺序。
-
怎么区分,怎么分类,字符,字符个数都相等的,才叫一类,
-
注意,出现的是字符串,依次访问字符串,还是不知道怎么区分。
思路
-
准备一个字符数组,26个,每个字符对应一个质数从2–101。int[] = primes
-
自己编写一个规则:拥有相同字符的字符串计算出来的值相同,这个值作为key区分不同字符串。
-
想到用int类型的值来区分不同类型的字符串,每个字符对应不同的数字,数字之和就代表这个字符串。
-
对于每个字符串,依次访问字符c , value * = primes[c - ‘a’]; value代表这个字符串,只有字符串中的字符相等,value就相等,区分不同字符串。
-
难点就是这个valuesum可以代表字符串,数学证明略,太菜不会。
-
HashMap<Integer, ArrayList> map = new HashMap<>();
-
遍历字符串数组,算出字符串的sum值作为key存放到map中,如果map中包含了这个key, 说明已经存在了这类字符串,添加到ArrayList中。
-
如果map还没包含这个key, 说明map里面还没有这类字符串,new 一个ArrayList()。
// int[] primes = {} // value代表一类字符串,value作为key, new ArrayList<>()作为value 放到map中 // value计算方法:value *= primes[c - 'a']; // 遍历字符串,计算str的value, 看map是否已经存有此类字符串,如果有,str添加到curList里 // 如果没有,则新建一个newList,专门用来存放此类字符串 // map的作用:遍历字符串时,查看是否包含此类字符串, 通过key快速得到此类字符串的容器curList
class Solution {
public List<List<String>> groupAnagrams(String[] strs) {
int[] primes = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29,
31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
73, 79, 83, 89, 97, 101};
HashMap<Integer, List<String>> map = new HashMap<>();
for(String s : strs) {
char[] chars = s.toCharArray();
int value = 1;
for(char c : chars) {
value *= primes[c - 'a'];
}
if(map.containsKey(value)) {
List<String> curList = map.get(value);
curList.add(s);
}else {
List<String> newList = new ArrayList<>();
newList.add(s);
map.put(value, newList);
}
}
return new ArrayList(map.values());
}
}
242. 有效的字母异位词
给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。
示例 1:
输入: s = “anagram”, t = “nagaram”
输出: true
示例 2:
输入: s = “rat”, t = “car”
输出: false
说明:
你可以假设字符串只包含小写字母。
进阶:
如果输入字符串包含 unicode 字符怎么办?你能否调整你的解法来应对这种情况?
// 准备int[] alpha = new int[26]
// 遍历s和t的所有字符,
// s 在字符的alpha数组对应位置上+1
// t 在字符的alpha数组对应位置上-1
// 如果s和t组成字符相等,则alpha被加减持平,还是0
class Solution {
public boolean isAnagram(String s, String t) {
if(s.length() != t.length()) {
return false;
}
int[] alpha = new int[26];
for(int i = 0; i < s.length(); i++) {
alpha[s.charAt(i) - 'a']++;
alpha[t.charAt(i) - 'a']--;
}
for(int i = 0; i < alpha.length; i++) {
if(alpha[i] != 0) {
return false;
}
}
return true;
}
}
438. 找到字符串中所有字母异位词
给定一个字符串 s 和一个非空字符串 p,找到 s 中所有是 p 的字母异位词的子串,返回这些子串的起始索引。
字符串只包含小写英文字母,并且字符串 s 和 p 的长度都不超过 20100。
说明:
字母异位词指字母相同,但排列不同的字符串。
不考虑答案输出的顺序。
示例 1:
输入:
s: “cbaebabacd” p: “abc”
输出:
[0, 6]
解释:
起始索引等于 0 的子串是 “cba”, 它是 “abc” 的字母异位词。
起始索引等于 6 的子串是 “bac”, 它是 “abc” 的字母异位词。
示例 2:
输入:
s: “abab” p: “ab”
输出:
[0, 1, 2]
解释:
起始索引等于 0 的子串是 “ab”, 它是 “ab” 的字母异位词。
起始索引等于 1 的子串是 “ba”, 它是 “ab” 的字母异位词。
起始索引等于 2 的子串是 “ab”, 它是 “ab” 的字母异位词。
// 和 一模一样,只不过一个输出true,一个输出left
// right一直向右,直到包含所有
// 在满足条件下,left++
// 如果window == needs.size() 则将left添加到答案中
class Solution {
public List<Integer> findAnagrams(String s, String p) {
List<Integer> ans = new ArrayList<>();
if(s == null || p == null) return ans;
if(s.length() == 0 || p.length() == 0) return ans;
char[] charsS = s.toCharArray(), charsP = p.toCharArray();
int lenS = charsS.length, lenP = charsP.length;
HashMap<Character, Integer> window = new HashMap<>();
HashMap<Character, Integer> needs = new HashMap<>();
for(int i = 0; i < lenP; i++) {
char c = charsP[i];
needs.put(c, needs.getOrDefault(c, 0) + 1);
}
int left = 0, right = 0, valid = 0;
while(right < lenS) {
while(right < lenS && valid < needs.size()) {
char in = charsS[right];
if(needs.containsKey(in)) {
window.put(in, window.getOrDefault(in, 0) + 1);
if(window.get(in).compareTo(needs.get(in)) == 0) {
valid++;
}
}
right++;
}
while(left < lenS && valid == needs.size()) {
if((right - left) == lenP) {
ans.add(left);
}
char out = charsS[left];
if(needs.containsKey(out)) {
window.put(out, window.getOrDefault(out, 1) - 1);
if(window.get(out) < needs.get(out)) {
valid--;
}
}
left++;
}
}
return ans;
}
}