目录
题目1:四数相加II
- 题目链接:454. 四数相加 II
1- 思路
- 本题要求求解的是四元组为 0 出现的次数,即四元组出现的次数
- 因此采用哈希法,因此利用 map 去存, k 存值 v 存次数
- 将 遍历前两个数组 A+B 将其值存入 map 中,之后通过再次遍历 CD数组,判断 map 中是否有 0-(C+D)
- 若有 则返回次数
2- 题解
⭐四数相加II ——题解思路
class Solution {
public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
Map<Integer,Integer> map = new HashMap<>();
int len1 = nums1.length;
int len2 = nums2.length;
int len3 = nums3.length;
int len4 = nums4.length;
int res = 0;
for(int i = 0; i < len1;i++ ){
for(int j = 0 ; j < len2;j++){
map.put(nums1[i]+nums2[j],map.getOrDefault(nums1[i]+nums2[j],0)+1);
}
}
for(int i = 0; i < len3;i++ ){
for(int j = 0 ; j < len4;j++){
if(map.containsKey(0-(nums3[i]+nums4[j]))){
res += map.get(0-(nums3[i]+nums4[j]));
}
}
}
return res;
}
}
题目2:赎金信
- 题目链接:383. 赎金信
1- 思路
- 定义哈希表,因为是判断字母出现次数,即利用一个 数组 作为 26 个字母的哈希即可
- 注意:看题说的是 前一个字符串能否由后一个组成,因此先求后一个的哈希,再求前一个的哈希
2- 题解
⭐赎金信 ——题解思路
class Solution {
public boolean canConstruct(String ransomNote, String magazine) {
int[] hash = new int[26];
for(int i = 0 ; i < magazine.length();i++){
hash[magazine.charAt(i)-'a']++;
}
for(int i = 0 ; i < ransomNote.length();i++){
hash[ransomNote.charAt(i)-'a']--;
}
for(int n:hash){
if(n<0){
return false;
}
}
return true;
}
}
题目3:三数之和 【5★】
- 题目链接:15. 三数之和
1- 思路
- 利用双指针,涉及去重逻辑
- 1.从 i 开始遍历数组,定义 left 和 right 指针,计算当前 sum
-
- 对下标 i 进行去重
-
- 根据当前 sum 的值判断指针移动的方式
-
- 在移动过程中对 left 和 right 去重
- 1. 元素 a 的去重
if (i > 0 && nums[i] == nums[i - 1]) { // 去重a
continue;
}
- 2. 元素 left 和 right 去重
- 去重逻辑应该放在找到 一个三元组之后
else {
result.add(Arrays.asList(nums[i], nums[left], nums[right]));
// 去重逻辑应该放在找到一个三元组之后,对b 和 c去重
while (right > left && nums[right] == nums[right - 1]) right--;
while (right > left && nums[left] == nums[left + 1]) left++;
right--;
left++;
}
2- 题解
⭐三数之和 ——题解思路
:::
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> res = new ArrayList<>();
// 先对 nums排序
Arrays.sort(nums);
for(int i = 0; i < nums.length;i++){
// 对 a 去重
if(i>0 && nums[i-1] == nums[i]){
continue;
}
// 定义左右指针
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{
res.add(Arrays.asList(nums[i],nums[left],nums[right]));
while(left<right && nums[left] == nums[left+1]) left++;
while(left<right && nums[right-1] == nums[right]) right--;
left++;
right--;
}
}
}
return res;
}
}
题目4:四数之和
- 题目链接:18. 四数之和
1- 思路
- 本题思路类似于三数之和,都是通过双指针的方式实现
- 本题注意去重逻辑有所不同
1.k 的去重逻辑
if(i>k+1 && nums[i-1] == nums[i]){
continue;
}
2.i 的去重逻辑⭐
if(i>k+1 && nums[i-1] == nums[i]){
continue;
}
3.left 和 right 的去重逻辑 同 三数之和
else{
res.add(Arrays.asList(nums[k],nums[i],nums[left],nums[right]));
while(left<right && nums[left] == nums[left+1]) left++;
while(left<right && nums[right] == nums[right-1]) right--;
left++;
right--;
}
2- 题解
⭐四数之和 ——题解思路
- ⭐i 的去重逻辑
- 2.3 利用 while
- 计算当前 sum 值,根据 sum 值判断 left 和 right 指针的移动方向
- 若 sum<target 证明当前需要更大的元素和 left++
- 若 sum>target 证明当前需要更小的元素和 right–
- ⭐否则二者相等,此时 收集结果集,同时在收集结果的时候 需要对 left 和 right 去重
:::
class Solution {
public List<List<Integer>> fourSum(int[] nums, int target) {
List<List<Integer>> res = new ArrayList<>();
Arrays.sort(nums);
for(int k = 0;k<nums.length;k++){
if(k>0 && nums[k-1] == nums[k]){
continue;
}
for(int i = k+1;i<nums.length;i++){
if(i>k+1 && nums[i-1] == nums[i]){
continue;
}
int left = i+1;
int right = nums.length-1;
while(left<right){
long sum = (long)nums[k] + nums[i] + nums[left]+nums[right];
if(sum<target){
left++;
}else if(sum>target){
right--;
}else{
res.add(Arrays.asList(nums[k],nums[i],nums[left],nums[right]));
while(left<right && nums[left] == nums[left+1]) left++;
while(left<right && nums[right] == nums[right-1]) right--;
left++;
right--;
}
}
}
}
return res;
}
}