滑动窗口、数组排序、计数法、哈希表
class Solution {
public boolean isAnagram(String s, String t) {
//s和t中每个字符出现的次数都相同,也就是说s和t的长度肯定相同
if(s.length() != t.length()){
return false;
}
HashMap<Character,Integer> map = new HashMap<>();
for (int i = 0; i < s.length(); i++) {
map.put(s.charAt(i),map.getOrDefault(s.charAt(i),0)+1);
map.put(t.charAt(i),map.getOrDefault(t.charAt(i),0)-1);
}
//若t与s有不同的字符,或相同字符的个数不同,则map中必有value<0的数
for (Integer value : map.values()) {
if(value < 0){
return false;
}
}
return true;
}
}
方法二:排序法
class Solution {
public boolean isAnagram(String s, String t) {
if (s.length() != t.length()) {
return false;
}
//s和t中每个字符出现的次数都相同,则其转换为字符数组并排序后,两数组相等
char[] str1 = s.toCharArray();
char[] str2 = t.toCharArray();
Arrays.sort(str1);
Arrays.sort(str2);
return Arrays.equals(str1, str2);
}
}
class Solution {
public boolean canConstruct(String ransomNote, String magazine) {
HashMap<Character,Integer> map = new HashMap<>();
//先遍历magazine,统计可用字符及其个数
for (int i = 0; i < magazine.length(); i++) {
char ch = magazine.charAt(i);
map.put(ch,map.getOrDefault(ch,0)+1);
}
for (int i = 0; i < ransomNote.length(); i++) {
char ch = ransomNote.charAt(i);
map.put(ch,map.getOrDefault(ch,0)-1);
if(map.get(ch) < 0){
return false;
}
}
return true;
}
}
class Solution {
public List<List<String>> groupAnagrams(String[] strs) {
//将字符串数组中的每个字符串转换成字符数组,并排序,以排序后字符数组组成的字符串为key,具有相同字母的字符串组成的list为value。
HashMap<String,List<String>> map = new HashMap<>();
for (String s: strs) {
char[] charArr = s.toCharArray();
Arrays.sort(charArr);
String str = String.valueOf(charArr);
List<String> list = map.getOrDefault(str,new ArrayList<>());
list.add(s);
map.put(str,list);
}
List<List<String>> ansList = new ArrayList<>(map.values());
return ansList;
}
}
方法一:排序法
class Solution {
public List<List<String>> groupAnagrams(String[] strs) {
//将字符串数组中的每个字符串转换成字符数组,并排序,以排序后字符数组组成的字符串为key,具有相同字母的字符串组成的list为value。
HashMap<String,List<String>> map = new HashMap<>();
for (String s: strs) {
char[] charArr = s.toCharArray();
Arrays.sort(charArr);
String str = String.valueOf(charArr);
List<String> list = map.getOrDefault(str,new ArrayList<>());
list.add(s);
map.put(str,list);
}
List<List<String>> ansList = new ArrayList<>(map.values());
return ansList;
}
}
class Solution {
public List<Integer> findAnagrams(String s, String p) {
//首先考虑长度关系
if(s.length() < p.length()){
return new ArrayList<Integer>();
}
//排序法
char[] charArr = p.toCharArray();
Arrays.sort(charArr);
String tmp = String.valueOf(charArr);
int j = 0;
List<Integer> list = new ArrayList<>();
for (int i = 0; i < s.length(); i++) {
if(i-j+1 == p.length()){
String str = s.substring(j,i+1);
char[] c = str.toCharArray();
Arrays.sort(c);
str = String.valueOf(c);
if(str.equals(tmp)){
list.add(j);
}
j++;
}
}
return list;
}
}
方法二:计数法
class Solution {
public List<Integer> findAnagrams(String s, String p) {
if(s.length() < p.length()){
return new ArrayList<>();
}
List<Integer> list = new ArrayList<>();
//记录p中每个字符的个数
int[] pCount = new int[26];
//记录s中每个字符的个数
int[] sCount = new int[26];
for (int i = 0; i < p.length(); i++) {
pCount[p.charAt(i)-'a']++;
}
int j = 0;
for (int i = 0; i < s.length(); i++) {
sCount[s.charAt(i)-'a']++;
if(i-j+1 == p.length()){
if(Arrays.equals(pCount,sCount)){
list.add(j);
}
sCount[s.charAt(j)-'a']--;
j++;
}
}
return list;
}
}
class Solution {
public int[] intersection(int[] nums1, int[] nums2) {
//题目中交集的意思是nums1与nums2共有的数,结果是不可重复的、无序的,因此可以使用HashSet存储
Set<Integer> set1 = new HashSet<>();
Set<Integer> set2 = new HashSet<>();
Set<Integer> set3 = new HashSet<>();
for (int i = 0; i < nums1.length; i++) {
set1.add(nums1[i]);
}
for (int i = 0; i < nums2.length; i++) {
set2.add(nums2[i]);
}
for(Integer i : set1){
if(set2.contains(i)){
set3.add(i);
}
}
int[] ans = new int[set3.size()];
int index = 0;
for(int i:set3){
ans[index++] = i;
}
return ans;
}
}
class Solution {
public int[] intersect(int[] nums1, int[] nums2) {
//与上一题相比,本题结果是可重复的、无序的,考虑使用HashMap存储
//key为交集中的元素,value为key出现的次数
int[] ans = new int[nums1.length];
int index = 0;
HashMap<Integer,Integer> map = new HashMap<>();
for (int i = 0; i < nums1.length; i++) {
map.put(nums1[i],map.getOrDefault(nums1[i],0)+1);
}
for (int i = 0; i < nums2.length; i++) {
if(map.containsKey(nums2[i]) && map.get(nums2[i])>0){
ans[index++] = nums2[i];
map.put(nums2[i], map.get(nums2[i])-1);
}
}
return Arrays.copyOfRange(ans,0,index);
}
}
class Solution {
public boolean isHappy(int n) {
//无限循环,也就是说,平方和会重复出现,考虑使用HashSet
HashSet<Integer> set = new HashSet<>();
while (true){
int sum = 0;
while (n>0){
sum += (n % 10) * (n % 10);
n /= 10;
}
if(sum == 1){
return true;
}
if(set.contains(sum)){
return false;
}
set.add(sum);
n = sum;
}
}
}
class Solution {
public int[] twoSum(int[] nums, int target) {
//本题需要返回数组下标,返回的元素不可重复,因此考虑使用HashMap存储
//key存储元素,value存储元素对应下标
//注意,nums数组可重复,可能有两个相同的数相加等于target
HashMap<Integer,Integer> map = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
if(map.containsKey(target-nums[i])){
return new int[]{map.get(target-nums[i]),i};
}
map.put(nums[i],i);
}
return new int[2];
}
}
class Solution {
public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
//因为题目只要求返回相加等于0的个数,因此可以只记录和数,与该和数出现的次数即可
//以和数为key,出现次数为value
int ans = 0;
HashMap<Integer,Integer> map = new HashMap<>();
for (int i = 0; i < nums1.length; i++) {
for (int j = 0; j < nums2.length; j++) {
int key = nums1[i]+nums2[j];
map.put(key,map.getOrDefault(key,0)+1);
}
}
for (int i = 0; i < nums3.length; i++) {
for (int j = 0; j < nums4.length; j++) {
int key = 0 - nums3[i] - nums4[j];
if(map.containsKey(key)){
ans += map.get(key);
}
}
}
return ans;
}
}