454. 四数相加 II
要求是给四个数组,要求的是满足
(i,j,k,l)=0的元素的数量有多少个
🍅 map解法(哈希表),即使用一个map存储前两个数组的元素之和以及它们出现的次数,然后通过判断满足题目条件的可能得出有几种满足题意的解。
要注意的是因为要快速判断是否存在与条件相符的值,并且要得到值出现的次数,所以采用map的方式来解题。还有这道题不同顺序的组合只要满足合为0,数量都会加一,也就是说组合是不去重的,那么最后返回的就应该是符合条件的valu之和。
class Solution {
public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
int count = 0; //count用来统计符合条件的值
Map<Integer,Integer> map1 = new HashMap<>();
//保存a+b和它出现的次数
for (int a: nums1) {
for (int b: nums2) {
int temp = (a+b);
if (map1.containsKey(temp)) {
map1.put(temp,map1.get(temp)+1);
}else
map1.put(temp,1);
}
}
//找出num3和num4符合条件的值有多少个
for (int c: nums3) {
for (int d: nums4) {
int temp = c+d;
if (map1.containsKey(0-temp)) {
count += map1.get(0-temp);
}
}
}
return count;
}
}
383. 赎金信
给你两个字符串:
ransomNote和magazine,判断ransomNote能不能由magazine里面的字符构成
🍅 数组解法(哈希表),即使用一个集合,一个集合录入magzine数组的元素,相比较一个字符串是否能由另一个字符串组成
这道题和之前242. 有效的字母异位词这道题类似,都是采用一个哈希映射数组。要注意的是这道题采用map的方式比较耗时,因为map结构相对数组结构要更耗时一点。
class Solution {
public boolean canConstruct(String ransomNote, String magazine) {
// 定义一个哈希映射数组
int[] record = new int[26];
// 遍历
for(char c : magazine.toCharArray()){
record[c - 'a'] += 1;
}
for(char c : ransomNote.toCharArray()){
record[c - 'a'] -= 1;
}
// 如果数组中存在负数,说明ransomNote字符串总存在magazine中没有的字符
for(int i : record){
if(i < 0){
return false;
}
}
return true;
}
}
15. 三数之和
给你一个整数数组
nums,判断是否存在三元组[nums[i], nums[j], nums[k]]满足i != j、i != k且j != k,同时还满足nums[i] + nums[j] + nums[k] == 0,并且三元组不可以重复
🍅 双指针解法,即用left和right两个指针,对数组元素进行筛选得出最后满足条件的3个元素。
要注意的是这道题用哈希表的方式太复杂,所以用双指针的方式来解决。另外双指针的思路实现比较简单,难的是3个元素中每个元素的去重。还有ArrayList的初始化最好使用List这个接口对他初始化,因为list接口的类更为广泛,要使用其他类时修改也比较方便。
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;
}
if (i>0 && nums[i] == nums[i-1]) { //对i下标的元素进行去重
continue;
}
int left = i+1; //定义left指针从i+1的地方开始
int right = nums.length-1; //定义right指针从最后一个元素开始
while (left < right) { //双指针不断向中间遍历,直至sum=0
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 (right>left && nums[right]==nums[right-1]) right--; //对left下标的元素进行去重
while (right>left && nums[left]==nums[left+1]) left++; //对right下标的元素进行去重
right--;
left++;
}
}
}
return res;
}
}
18. 四数之和
给你一个由 n 个整数组成的数组
nums,和一个目标值target。请你找出并返回满足下述全部条件且不重复的四元组[nums[a], nums[b], nums[c], nums[d]]==target,并且四元组不可以重复
🍅 双指针解法,即用left和right两个指针,对数组元素进行筛选得出最后满足条件的3个元素。
这道题和15. 三数之和类似,都是要找去重后的数组。要注意的是这道题的target不是固定等于0的,所以通过i下标的元素判断是否大于target这样的筛选是错误的。还有这道题最后一个案例的元素值较大,需用long强制转换sum,这样返回的结果才是正确的。
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] > target && nums[i] >= 0) {
break; // 这里使用break,统一通过最后的return返回
}
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;
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]; //强制类型转换,有个案例的值太大要用long
if (sum > target) {
right--;
}
else if (sum < target) {
left++;
}
else{
res.add(Arrays.asList(nums[i], nums[j], nums
[left], nums[right]));
while (right>left && nums[right]==nums[right-1]
) right--; //对right去重
while (right>left && nums[left]==nums[left+1]
) left++; //对left去重
right--;
left++;
}
}
}
}
return res;
}
}
如果对哈希表数据结构不熟悉或者刷题没有思路的,这边推荐卡哥的网站,里面有文字讲解和视频,我也是跟着卡哥学习的。