哈希表
1、数组作为哈希表
数组是一个简单的哈希表。题目中字符串只有小写字符,那么就可以定义一个数组,来记录字符串s里字符出现的次数(利用了字符的ASCII码可转换为整型)
技巧:只涉及小写字母,考虑用数组作为哈希表
代码实现为:
class Solution {
public boolean isAnagram(String s, String t) {
int[] array = new int[128];
if(s.length()!=t.length()){
return false;
}
for(int i = 0;i<s.length();i++){
array[s.charAt(i)]++;
}
for(int i = 0;i<t.length();i++){
array[t.charAt(i)]--;
}
for(int count:array){
if(count!=0){
return false;
}
}
return true;
}
}
与上题思路大同小异,只需注意判断哪个字符串的字符是可以多出的,哪个不行即可
代码实现为:
class Solution {
public boolean canConstruct(String ransomNote, String magazine) {
int[] array = new int[128];
for(int i =0;i<ransomNote.length();i++){
array[ransomNote.charAt(i)]++;
}
for(int i =0;i<magazine.length();i++){
array[magazine.charAt(i)]--;
}
for(int count:array){
if(count>0){
return false;
}
}
return true;
}
}
代码实现为:
class Solution {
public List<List<String>> groupAnagrams(String[] strs) {
Map<String,List<String>> hashmap = new HashMap<>();
for(String str:strs){
char[] array = str.toCharArray();
Arrays.sort(array);
String key = new String(array);
List<String> list = hashmap.getOrDefault(key,new ArrayList<String>());
list.add(str);
hashmap.put(key,list);
}
return new ArrayList<List<String>>(hashmap.values());
}
}
结合滑动窗口解决问题
代码实现为:
class Solution {
public List<Integer> findAnagrams(String s, String p) {
int[] need = new int[128];
int[] window = new int[128];
List<Integer> res = new ArrayList<>();
for(int i = 0;i<p.length();i++){
need[p.charAt(i)]++;
}
//移动窗口
int left = 0,right = 0;
int count = 0;
while(right<s.length()){
char ch = s.charAt(right);
window[ch]++;
//更新窗口位置
//概念别混淆:cbba不是abc的异位词
while(window[ch]>need[ch]){
char rem = s.charAt(left);
window[rem]--;
left++;
}
//保证字符数一致
if(right-left+1 == p.length()){
res.add(left);
}
right++;
}
return res;
}
}
Arrays.copyOfRange()
是 Java 中用于复制指定范围的数组元素到一个新数组的方法
代码实现为:
class Solution {
public int[] intersect(int[] nums1, int[] nums2) {
Map<Integer,Integer> hashmap = new HashMap<>();
int[] res = new int[nums1.length];
int index = 0;
for(int num:nums1){
hashmap.put(num,hashmap.getOrDefault(num,0)+1);
}
for(int num:nums2){
if(hashmap.containsKey(num) && hashmap.get(num)>0){
res[index++] = num;
hashmap.put(num,hashmap.get(num)-1);
}
}
return Arrays.copyOfRange(res,0,index);
}
}
2、set作为哈希表
代码实现为:
class Solution {
public int[] intersection(int[] nums1, int[] nums2) {
Set<Integer> set = new HashSet<>();
Set<Integer> resSet = new HashSet<>();
int n = Math.min(nums1.length,nums2.length);
int[] res = new int[n];
for(int num:nums1){
set.add(num);
}
for(int num:nums2){
if(set.contains(num)){
resSet.add(num);
}
}
//set转为数组
return resSet.stream().mapToInt(x->x).toArray();
}
}
代码实现为:
class Solution {
public boolean isHappy(int n) {
Set<Integer> set = new HashSet<>();
while(set.add(n)){
n = nextNumber(n);
}
return n==1;
}
private int nextNumber(int n){
int res = 0;
while(n>0){
int tmp = n%10;
res += tmp*tmp;
n = n/10;
}
return res;
}
}
3、map作为哈希表
class Solution {
public int[] twoSum(int[] nums, int target) {
Map<Integer,Integer> hashmap = new HashMap<>();
for(int i = 0;i<nums.length;i++){
if(hashmap.containsKey(target-nums[i])){
return new int[]{i,hashmap.get(target-nums[i])};
}
hashmap.put(nums[i],i);
}
return new int[0];
}
}
class Solution {
public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
//哈希表key记录两数组之和,value记录次数
Map<Integer,Integer> hashmap = new HashMap<>();
int res = 0;
for(int num1:nums1){
for(int num2:nums2){
int sum = num1+num2;
hashmap.put(sum,hashmap.getOrDefault(sum,0)+1);
}
}
for(int num3:nums3){
for(int num4:nums4){
if(hashmap.containsKey(0-num3-num4)){
res += hashmap.get(0-num3-num4);
}
}
}
return res;
}
}
4、其他
与上题不同,本题需要去重,若用哈希表会十分复杂,故采用双指针方法
代码实现为:
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> res = new ArrayList<>();
Arrays.sort(nums);
for(int i = 0;i<nums.length;i++){
if(nums[i]>0){
return res;
}
//nums[i]去重
if(i>0 && nums[i]==nums[i-1]){
continue;
}
int left = i+1,right = nums.length-1;
while(left<right){
int sum = nums[i]+nums[left]+nums[right];
if(sum>0){
right--;
}else if(sum<0){
left++;
}else{
res.add(Arrays.asList(nums[i],nums[left],nums[right]));
//nums[left]、nums[right]去重
while(left<right && nums[right]==nums[right-1])right--;
while(left<right && nums[left]==nums[left+1])left++;
//先去重,再动指针
right--;
left++;
}
}
}
return res;
}
}
与上题类似
代码实现为:
class Solution {
public List<List<Integer>> fourSum(int[] nums, int target) {
List<List<Integer>> res = new ArrayList<>();
Arrays.sort(nums);
for(int i = 0;i<nums.length;i++){
if(nums[i]>0 && nums[i]>target){
return res;
}
//给nums[i]去重
if(i>0 && nums[i]==nums[i-1]){
continue;
}
for(int j = i+1;j<nums.length;j++){
//给nums[j]去重
if(j>i+1 && nums[j]==nums[j-1]){
continue;
}
int left = j+1,right = nums.length-1;
while(left<right){
long sum = nums[i]+nums[j]+nums[left]+nums[right];
if(sum>target){
right--;
}else if(sum<target){
left++;
}else{
res.add(Arrays.asList(nums[i],nums[j],nums[left],nums[right]));
//给nums[left]、nums[right]去重
while(right>left && nums[right]==nums[right-1])right--;
while(right>left && nums[left]==nums[left+1])left++;
right--;
left++;
}
}
}
}
return res;
}
}