文章目录
一、LeetCode454.四数相加II
链接:454. 四数相加 II - 力扣(LeetCode)
方法:map作哈希表
1. 思路
题目要求的是四个数组直接相加等于某一个数,不用考虑到数组组合相加的重复情况。让ab数组进行相加在减去bc数组相加值如果等于0,那么就代表这是一个复合条件的数组相加。
解题步骤:
- 创建map,key保存 a+b 的值,value 保存出现的次数
- 遍历计算 ab数组,把结果存入map中
- 遍历计算 cd 数组,和map里面结果进行比对,复合 a+b = 0 - (c+d),则 count 加 value
2. 代码实现
class Solution {
public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
Map<Integer, Integer> map = new HashMap<>();
int temp = 0;
int count = 0;
// 计算 a + b 存入 map
for(int num1 : nums1){
for(int num2: nums2){
temp = num1 + num2;
if(map.containsKey(temp)){
map.put(temp, map.get(temp) + 1);
}else{
map.put(temp,1);
}
}
}
// 计算 b + c,查询 map 中 复合 0 - (b + c) 的值
for(int num3 : nums3){
for(int num4 : nums4){
temp = num3 + num4;
if(map.containsKey(0 - temp)){
count += map.get(0 - temp);
}
}
}
return count;
}
}
3.复杂度分析
时间复杂度:O(N^2)
空间复杂度:O(N)
3.思考
- 为啥会想到用哈希法?这里是先计算了前两个数组的结果,然后再计算后两个数组计算的结果,去进行查询,可以想到用哈希法。
- 这题因为不用考虑重复的问题,所以可以使用map做哈希表,使用key保存计算结果,value保存次数。
- 做题时,如果发现题目是要进行查询的,那么应该首先想到能不能用哈希法去做。
Reference
二、LeetCode383. 赎金信
链接:Loading Question… - 力扣(LeetCode)
方法:数组作哈希表
1. 思路
这题和 242.有效的字母异位词 类似,这题的要求是,字符串b能否组成字符串a。
2. 代码实现
class Solution {
public boolean canConstruct(String ransomNote, String magazine) {
int[] record = new int[26];
for(char i:magazine.toCharArray()){
record[i-'a']++;
}
for(char j:ransomNote.toCharArray()){
record[j-'a']--;
if(record[j-'a'] < 0){
return false;
}
}
return true;
}
}
3. 复杂度分析
时间复杂度:O(N)
空间复杂度:O(1)
Reference
三、LeetCode15. 三数之和
链接:Loading Question… - 力扣(LeetCode)
方法:双指针解法
1. 思路
首先需要对数组进行排序,然后一层for
循环,i
从下标0
开始遍历,left
为 i+1
,right
为数组结尾的位置。数组 a + b + c = 0
,可以转为i + left + right = 0
。
如何移动 left
和 right
的下标,当i + left + right > 0
时,可以right—
,小于0
可以left++
。
2. 代码实现
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> result = new ArrayList<>();
Arrays.sort(nums);
for(int i = 0; i < nums.length; i++){
// 因为是顺序数组,开头大于零就没有计算的意义了
if(nums[i] > 0){
return result;
}
// 对 a 进行去重
if(i>0 && nums[i] == nums[i-1]){
continue;
}
int left = i + 1;
int right = nums.length-1;
while(right > left){
int sum = nums[i] + nums[left] + nums[right];
if(sum > 0){
right--;
}else if(sum < 0){
left++;
}else{
result.add(Arrays.asList(nums[i], nums[left], nums[right]));
// 对 c 进行去重
while(right > left && nums[right] == nums[right-1]){
right--;
}
// 对 b 进行去重
while(right > left && nums[left] == nums[left+1]){
left++;
}
right--;
left++;
}
}
}
return result;
}
}
3. 复杂度分析
时间复杂度:O(N^2)
4.思考
- 需要把去重的逻辑给思考清楚。
Reference
四、LeetCode18.四数之和
链接:Loading Question… - 力扣(LeetCode)
方法:双指针解法
2. 代码实现
class Solution {
public List<List<Integer>> fourSum(int[] nums, int target) {
List<List<Integer>> result = new ArrayList<>();
Arrays.sort(nums);
for(int k = 0; k < nums.length; k++){
// 剪枝操作,考虑到可能为负数的情况
if(nums[k] > 0 && nums[k] > target){
return result;
}
// k 去重
if(k > 0 && nums[k-1] == nums[k]){
continue;
}
// 二级循环 k,i,left,right
for(int i = k + 1; i < nums.length; i++){
// 二级剪枝
if(nums[i] + nums[k] > target && nums[i] + nums[k] >= 0){
break;
}
// i 去重
if(i > k + 1 && nums[i-1] == nums[i]){
continue;
}
int left = i + 1;
int right = nums.length-1;
while(right > left){
long sum = (long)nums[k] + nums[i] + nums[left] + nums[right];
if(sum > target){
right--;
}else if(sum < target){
left++;
}else{
result.add(Arrays.asList(nums[k] , nums[i], nums[left], nums[right]));
// 对 c 进行去重
while(right > left && nums[right] == nums[right-1]) right--;
// 对 d 进行去重
while(right > left && nums[left] == nums[left+1]) left++;
left++;
right--;
}
}
}
}
return result;
}
}
Reference