454.两数相加Ⅱ
题目链接:. - 力扣(LeetCode)
题目讲解:代码随想录
1)解题思路:
- 首先定义一个HashMap,key放a和b两数之和,value 放a和b两数之和出现的次数。
- 遍历大A和大B数组,统计两个数组元素之和,和出现的次数,放到map中。
- 定义int变量count,用来统计 a+b+c+d = 0 出现的次数。
- 再遍历大C和大D数组,找到如果 0-(c+d) 在map中出现过的话,就用count把map中key对应的value也就是出现次数统计出来。
- 最后返回统计值 count 就可以了.
2)代码实现:
class Solution {
public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
//1. 定义一个hashmap,key放两数之和,value放两数之和出现的次数
Map<Integer,Integer> hash = new HashMap<>();
//2. 遍历大A和大B数组,记录两个数组元素之和
for(int i = 0; i < nums1.length;i++){
for(int j = 0; j < nums2.length;j++){
hash.put(nums1[i]+nums2[j], hash.getOrDefault(nums1[i]+nums2[j],0)+1);
}
}
//3.定义计数器
int count = 0;
//4. 遍历其他两个数组,统计个数
for(int i = 0; i < nums3.length;i++){
for(int j = 0; j < nums4.length ; j++){
if(hash.getOrDefault(0-nums3[i]-nums4[j] , 0) != 0){
count += hash.getOrDefault(0-nums3[i]-nums4[j] , 0);
}
}
}
return count;
}
}
15.三数之和
题目链接:. - 力扣(LeetCode)
题目讲解:代码随想录
1)解题思路:
(1)a+b+c = 0 转化为 nums[i] + nums[right] + nums[left] = 0
(2)!!现将数组排序
(3)i是放在数组左端(外层循环控制),right是放在数组右端,left在i和right之间移动,寻找三者和为0的搭配。
(4)内层循环逻辑:left在i和right之间移动,
i)nums[i] + nums[left] + nums[right] == 0 ,记录在答案中,向左寻找(left++)
ii)nums[i] + nums[left] + nums[right] > 0,说明此时的最大数nums[right]太大了,右边界向右移动(right--),
iii)nums[i] + nums[left] + nums[right] < 0,说明此时的总数太小了,继续向左移动left(left++)
(5)当 right 和 left 相遇时,即可停止。
(6)本题有去重的操作,不能有重复的三元组排列,但是组内三个元素是可以重复的
在每一次发现搭配存入答案数组中之后,都需要去重,保证下一次搭配出现不与上一次搭配重复。但需要针对除第一个元素之外的其他元素进行去重,防止[-1,-1,2]这种被卡掉。
2)代码实现:
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
//1.新建一个数组,存放结果
List<List<Integer>> ans = new ArrayList<>();
//2.双指针先排好序
Arrays.sort(nums);
//3.循环查找
for(int i = 0; i < nums.length;i++){
//判断合法,三元组里面最小的元素大于0,没有循环的必要
if(nums[i] > 0){
break;
}
//对i进行去重,非首项的三元组中最小元素如果和上一次循环的一样,结果也一样
//去除这种可能,和上一项相同的i抛弃,进入下一次循环
if(i > 0 && nums[i] == nums[i-1]){
continue;
}
//双指针法进行查找
//left是中间的迭代元素,right是三元组中最大的元素
int left = i+1;
int 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{
ans.add(Arrays.asList(nums[i],nums[left],nums[right]));
//对left去重,left向左移动找到与现在不同的元素
while(left < right && nums[left] == nums[left+1])left++;
//对right去重,right向右移动,找到与现在相同的最右边的元素
while(left < right && nums[right] == nums[right - 1])right--;
left++;right--;
}
}
}
return ans;
}
}
18.四数之和
题目链接:. - 力扣(LeetCode)
题目讲解:代码随想录
1)解题思路:
四数之和的双指针解法是两层for循环nums[k] + nums[i]为确定值,依然是循环内有left和right下标作为双指针,找出nums[k] + nums[i] + nums[left] + nums[right] == target的情况。
三数之和的时间复杂度是O(n^2),四数之和的时间复杂度是O(n^3) 。
2)代码实现:
class Solution {
public List<List<Integer>> fourSum(int[] nums, int target) {
//1.新建一个返回类型的答案数组
List<List<Integer>> ans = new ArrayList<>();
//2.双指针先浅浅排序一下
Arrays.sort(nums);
//3.两层循环算nums[a] + nums[b]
//left是nums[c],right是nums[d]
for(int i = 0;i < nums.length;i++){
//(剪枝处理)对四元组中最小元素,做合法判别
if(nums[i] > target && nums[i] > 0){
break;
}
//对四元组中的nums[a]去重,
if(i > 0 && nums[i] == nums[i-1]){
continue;
}
for(int j = i+1;j < nums.length;j++){
//(剪枝处理)
if(nums[i] + nums[j] > target && nums[i] + nums[j] >= 0){
break;
}
//对nums[b]去重
if(j > i + 1 && nums[j] == nums[j-1]){
continue;
}
//双指针
int left = j+1;
int right = nums.length-1;
while(left < right){
long sum =(long)nums[i] + nums[j] + nums[left] + nums[right];
if(sum > target){
right--;
}else if(sum < target){
left++;
}else{
ans.add(Arrays.asList(nums[i],nums[j],nums[left],nums[right]));
//对left进行去重,循环找到left最后一个重复元素
while(left < right && nums[left] == nums[left + 1])left++;
//对right进行去重,循环找到right最后一个重复元素
while(left < right && nums[right] == nums[right - 1])right--;
left++;right--;
}
}
}
}
return ans;
}
}
哈希表小结
1)三种哈希表数据结构:
数组哈希表 | int[] hash = new hash (key-为坐标,value为数组元素值) | 需要提前知道哈希表大小 | 242.有效的字母异位词 383.赎金信 |
---|---|---|---|
set哈希表 | Set<Integer> ans = new HashSet<>(); (单列存储,只储存键值) | 单列存储,只能存储键值 | 349.两个数组的交集 202.快乐数 |
map哈希表 | Map<Integer,Integer> ans = new HashMap<>(); (存储键值对,Key唯一) | 存储键值对 | 1.两数之和 454.四数之和 |
2)HashSet常用方法:
//引入hashset类的封装包
import java.util.HashSet;
import java.util.Set;
//创建HashSet对象
Set<Integer> set1 = new HashSet<>();
//遍历数组1
for (int i : nums1) {
//添加元素
set1.add(i);
}
//查看哈希表中是否存在key值为i的元素
set1.contains(i)
//把HashSet集合转为数组
resSet.stream().mapToInt(x -> x).toArray();
3)HashMap常用方法:
getOrDefault(K key , V deflautValue) 根据指定的键获取对应的值,没有则返回后面那个默认数值。