前言
本文是根据代码随想录中哈希表内容的顺序进行的 代码随想录
其他文章链接:刷算法Leetcode文章汇总
哈希表篇
①使用 Map 或 26位int数组 统计每种字符的个数
②比较两串字符排序结果,应该一样
①两个Set,一个找两个数组的重合字符,另一个保存结果,再将Set转为Array返回
②排序+双指针,两指针字符相同且与上一个匹配字符不同,就加入
完成计算一个数位平方和的算法,使用%和/操作
此题关键在于,找到快乐数的规律,平方和永远达不到1是因为进入了死循环(详细见官方对每种位数平方和的验证),因此问题转换为是否进入循环
①Set判断重复,是否进入循环
②快慢指针,判断是否相遇
③数学方法,证明只存在唯一一个循环,先找到循坏中的所有数,判断实际是否遇到
①暴力求解,双重循环
②Map存储value-index,找target-value是否存在,返回下标
①暴力求解超时
②分组,两个Map,分记录一二组和三四组的每种sum-num,再对其中一个Map找另一个Map中的-sum,求种数乘积和
③分组,一个Map记录一二组的每种sum-num,遍历三四找到对应-num3-num4的种数,求和
class Solution {
public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
int num = 0;
Map<Integer,Integer> sum = new HashMap<>();
for(int a : nums1){
for(int b : nums2){
sum.put(a+b, sum.getOrDefault(a+b, 0)+1);
}
}
for(int c : nums3){
for(int d : nums4){
if(sum.containsKey(-c-d))num += sum.get(-c-d);
}
}
return num;
}
}
长度边界值判断
①使用 Map 或 26位int数组 统计magazine中的字符数,再对Note中的每个字符数-1
②排序+双指针,字符相同都后移,不同只移动magazine的指针,判断note的指针是否在最后
要求三元组值不重复,可以排序后遍历,要求当前指针的值与指针前一个值不相等
①排序+暴力三重循环,超时
②排序+双指针,先确定第一个数,剩下两个使用双指针在有序数组中找到目标和
优化:第一个数确定后
1)如果nusm[i]+nums[i+1]+nums[i+2]>target,此后遍历不会有等于结果,直接返回
2)如果nusm[i]+nums[n-2]+nums[n-1]<target,当前nums不会有满足结果,进入下一个循环
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> res = new ArrayList<>();
int n = nums.length;
Arrays.sort(nums);
for(int i = 0; i < n; i++){
if(i+2<n&&nums[i]+nums[i+1]+nums[i+2]>0)return res;
if(nums[i]+nums[n-1]+nums[n-1]<0)continue;
if(i > 0 || nums[i] == nums[i-1])continue;
int z = n-1;
int target = -nums[i];
for(int j =i+1;j<n;j++){
if(j ==i+1||nums[j]!=nums[j-1]){
while(j<z&&nums[j]+nums[z]>target)z--;
if(j==z)break;
if(nums[j]+nums[z]==target)
res.add(Arrays.asList(nums[i], nums[j], nums[z]));
}
}
}
return res;
}
}
与上一个题三数之和类似,先排序再判断是否与前一个重复
①排序+暴力四重循环,超时
②排序+双指针,与三数之和不同的是,每次确定前两个数,另外两个使用双指针
优化:分两种情况:确定第一个数(找另三个数) 和 确定前两个数(找另两个数)
1)与随后 三 / 两 个数的和大于target,break
2)与最后 三 / 两 个数的和小于target,continue;
class Solution {
public List<List<Integer>> fourSum(int[] nums, int target) {
List<List<Integer>> res = new ArrayList<>();
if(nums==null||nums.length<4)return res;
Arrays.sort(nums);
int n = nums.length;
for(int i = 0; i < n-3; i++){
if(i>0&&nums[i]==nums[i-1])continue;
if((long)nums[i]+nums[i+1]+nums[i+2]+nums[i+3]>target)break;
if((long)nums[i]+nums[n-3]+nums[n-2]+nums[n-1]<target)continue;
for(int j=i+1;j<n-2;j++){
if(j>i+1&&nums[j]==nums[j-1])continue;
if((long)nums[i]+nums[j]+nums[j+1]+nums[j+2]>target)break;
if((long)nums[i]+nums[j]+nums[n-2]+nums[n-1]<target)continue;
int l = j+1, r=n-1;
while(l<r){
if(l>j+1&&nums[l]==nums[l-1]){l++;continue;}
if(r<n-1&&nums[r]==nums[r+1]){r--;continue;}
long sum = (long)nums[i]+nums[j]+nums[l]+nums[r];
if(sum==target){
res.add(Arrays.asList(nums[i],nums[j],nums[l],nums[r]));
l++;
r--;
}
else if(sum<target)l++;
else r--;
}
}
}
return res;
}
}
哈希表总结:
1、Map可用于value-index,或者value-sum
2、统计个数,使用Map或者数组,特别是对于26个小写字母,可以使用26位int数组计数
3、判断重复/循环,使用Set
4、对于数和问题,两位数之和使用Map记录value-index,三位/四位数之和使用排序+双指针,四位数之和Ⅱ(不考虑重复问题)使用Map记录sum-num